Angular powered owl-carousel
npm install ngx-owl-carousel-ongx-owl-carousel-o is built for Angular >=6.0.0. It doesn't use jQuery.
WARNING: The version 20.1.0 introduces accessibility features with breaking changes for navigation buttons (prev/next) HTML structure and CSS.
So if you update the lib from the version <20.1.0 to >=20.1.0, you need to update your custom styles for navigation buttons.
ngx-owl-carousel-o | Angular
------------------------|--------
21.x.x | 21.x.x
20.x.x (latest 20.1.0)| 20.x.x
19.x.x (latest 19.0.2)| 19.x.x
18.x.x (latest 18.0.1)| 18.x.x
17.x.x (latest 17.0.1)| 17.x.x
16.x.x (latest 16.0.1)| 16.x.x
15.x.x (latest 15.0.2)| 15.x.x
14.x.x (latest 14.0.2)| 14.x.x
7.x.x (latest 7.0.5) | 13.x.x
6.x.x (latest 6.0.3) | 12.x.x
5.x.x (latest 5.1.2) | 11.x.x
4.x.x (latest 4.1.2) | 10.x.x
3.x.x (latest 3.1.1) | 9.x.x
2.x.x (latest 2.1.2) | 8.x.x
1.x.x (latest 1.2.1) | 7.x.x
0.x.x (latest 0.1.2) | 6.x.x
- Get started
- Setting custom slides ids
- Options
- How to refresh the carousel if options change
- Tag in the slide. Directive owlRouterLink
- Events
- Plugins
- Tips
- ReferenceError: Event is not defined
- Using ngx-owl-carousel-o slide data in custom code
- Issue: autoplay doesnt stay paused when user opens mat-menu
- Accessibility
1. Run yarn add ngx-owl-carousel-o or npm install ngx-owl-carousel-o.
2. Add styles (one of these variants).
- angular.json:
``json`
"styles": [
"node_modules/ngx-owl-carousel-o/lib/styles/prebuilt-themes/owl.carousel.min.css",
"node_modules/ngx-owl-carousel-o/lib/styles/prebuilt-themes/owl.theme.default.min.css",
"src/styles.sass" or "src/styles.css"
],
- src/styles.sass or src/styles.scss:
`sass`
@use 'ngx-owl-carousel-o/lib/styles/scss/owl.carousel';
@use 'ngx-owl-carousel-o/lib/styles/scss/owl.theme.default' as owl-theme;
3. Import RouterModule and Routes into AppModule unless they are imported.CarouselModule
4. Import into a module which declares a component intended to have a carousel.
`typescript`
import { CarouselModule } from 'ngx-owl-carousel-o';
@NgModule({
imports: [ CarouselModule ],
declarations: [ CarouselHolderComponent ]
})
export class SomeModule { }
5. Add to needed component customOptions or named in different way object with options for the carousel:
`typescript`
import { OwlOptions } from 'ngx-owl-carousel-o';
import { Component } from "@angular/core";
@Component({
selector: '....',
templateUrl: 'carousel-holder.component.html'
})
export class CarouselHolderComponent {
customOptions: OwlOptions = {
loop: true,
mouseDrag: false,
touchDrag: false,
pullDrag: false,
dots: false,
navSpeed: 700,
navText: ['', ''],
responsive: {
0: {
items: 1
},
400: {
items: 2
},
740: {
items: 3
},
940: {
items: 4
}
},
nav: true
}
slidesStore = signal
{ id: 'slide-1', text: 'Slide 1 HM', dataMerge: 2, width: 300, dotContent: 'text1' },
{ id: 'slide-2', text: 'Slide 2 HM', dataMerge: 1, width: 500, dotContent: 'text2' },
{ id: 'slide-3', text: 'Slide 3 HM', dataMerge: 3, width: 500, dotContent: 'text3' },
{ id: 'slide-4', text: 'Slide 4 HM', width: 450, dotContent: 'text4' },
{ id: 'slide-5', text: 'Slide 5 HM', dataMerge: 2, width: 500, dotContent: 'text5' },
{ id: 'slide-6', text: 'Slide 6', width: 500, dotContent: 'text5' },
{ id: 'slide-7', text: 'Slide 7', width: 500, dotContent: 'text6' },
{ id: 'slide-8', text: 'Slide 8', width: 500, dotContent: 'text8' },
// { id: 'slide-7', text: 'Slide 7', dotContent: 'text5'},
// { id: 'slide-8', text: 'Slide 8', dotContent: 'text5'},
// { id: 'slide-9', text: 'Slide 9', dotContent: 'text5'},
// { id: 'slide-10', text: 'Slide 10', dotContent: 'text5'},
]);
}
6. Add html-markup to the template of the component (in this case, add it to carousel-holder.component.html):
`html`
Some tags before
Some tags after
or
`html
Some tags before
@for (slide of slidesStore(); track slide.id) {
}
NOTE: Each slide has an
id. If it isn't supplied like in the first example given to p. 7, the code generates it automatically and expose one when the event translated fires. Info about this event is below. Follow the link event translated.NOTE: Custom
id must have the type string.NOTE: Using ngx-owl-carousel-o with options
animateOut and animateIn requires adding animate.css. Steps are the following:1.
yarn add animate.css or npm install animate.css.
2. Add styles to angular.json:
`json
"styles": [
"node_modules/animate.css/animate.min.css"
],
`Setting custom slides ids
It's possible to set own id to every slide.
> Every
id must have the type string. Otherwise, slides won't get ids what will cause one problem, which appears when the developer uses the option responsive. Slides won't be shown when the width of the screen changes and the carousel has to apply new settings according to the defined breakpoint. This is because the code uses ids of slides in order to assign new data to slides. So if you change the width of the screen and slides disappear, there could be the problem with setting id.
> If ids aren't set explicitly, they will be created automatically.The example of setting
ids:`html
Some tags before
@for (slide of slidesStore(); track slide.id) {
![]()
}
Some tags after
`Options
ngx-owl-carousel-o uses the same options as Owl Carousel. Explanations of meanings and the usage of options are in Owl Carousel Documentation.
NOTE: ngx-owl-carousel-o has the different usage of some of them. Mostly this is about options which require setting
data- attributes to DOM-elements and which set names of classes and tags in the HTML-markup. The usage of these options is explained below.Options which require setting
data- attributes are:- merge
- dotsData
- URLhashListener
- lazyLoad
$3
The original Owl Carousel requires setting
data-merge to each slide besides setting merge=true. In this lib data-merge is changed to dataMerge , which is the @Input property of the directive. The way of setting it is:`html
Slide text or HTML markup
` the
number must be 1, 2, 3 or any other integer numbers. If dataMerge isn't provided, its value will be 1 (this is the default value).$3
The option
autoWidth=true is working if user sets the @Input prop width to directive. The example:`html
Slide text or html markup
`When the
width isn't provided for a certain slide and is provided for other slides, firstly it will be 0 (this is the default value). At the end it will be calculated as (width of carousel)/(items) (e.g. carouselWidth=1200 and items=4, the width of the slide will be 1200/4=300).In other words, the width of the slide with unprovided
width will be set according to how much space in visible carousel window the slide must take. E.g. if there must be 2 visible slides, the width of the item will be half of the carousel window.$3
The option
responsiveBaseElement doesn't work. In the original Owl Carousel, all responsive breakpoints are corresponding to window width. Here they are corresponding to the width of the element which takes 100% of its parent element width.$3
The option
fallbackEasing doesn't work because it's being used by $.animate() in Owl Carousel created by means of jQuery. There's no such function in Angular.$3
The option
info doesn't work.$3
These options don't work.
| Option | Explanation |
| ------------------------------- | -----------------------------------------------------------------------------------------|
| navElement: 'div' | this tag is set explicitly in the View of CarouselComponent |
| navContainer: false | is removed |
| navContainerClass: 'owl-nav' | this css-class is set explicitly in the View of CarouselComponent |
| navClass: [ 'owl-prev', 'owl-next' ] | this css-class is set explicitly in the View of CarouselComponent |
| dotClass: 'owl-dot' | this css-class is set explicitly in the View of CarouselComponent |
| dotsClass: 'owl-dots' | this css-class is set explicitly in the View of CarouselComponent |
| dotsContainer: false | is removed |
$3
The option
nestedItemSelector doesn't work.$3
These options don't work.
| Option | Explanation |
| ------------------------------- | ---------------------------------------------------------------------------------------------|
| itemElement: 'div' | this tag is set explicitly in the View |
| itemClass: 'owl-item' | this css-class is set explicitly in the View |
| stageElement: 'div' | this tag is set explicitly in the View |
| stageClass: 'owl-stage' | this css-class is set explicitly in the View |
| stageOuterClass: 'owl-stage-outer'| this css-class is set explicitly in the View |
| | |
| refreshClass: 'owl-refresh' | this css-class is removed. Class 'owl-refreshed' is used instead. It's set explicitly in the View and reflected by OwlDOMData.isRefreshed |
| loadedClass: 'owl-loaded' | this css-class is set explicitly in the View and reflected by OwlDOMData.isLoaded |
| loadingClass: 'owl-loading' | this css-class is set explicitly in the View and reflected by OwlDOMData.isLoading |
| rtlClass: 'owl-rtl' | this css-class is set explicitly in the View and reflected by OwlDOMData.rtl |
| responsiveClass: 'owl-responsive' | this css-class is set explicitly in the View and reflected by OwlDOMData.isResponsive |
| dragClass: 'owl-drag' | this css-class is set explicitly in the View and reflected by OwlDOMData.isDragable |
| grabClass: 'owl-grab' | this css-class is set explicitly in the View and reflected by OwlDOMData.isGrab |
$3
NOTE: Setting options in the HTML-template in the way like
`html
', '
Slide
`will cause the template parse error because of the double quote put around classes's names _fa-chevron-left_ and _fa-chevron-right_. The creation of the property e.g.
customOptions in component.ts and writing [options]="customOptions" will eliminate this problem.`typescript
customOptions: OwlOptions = {
navText: [ '', '}
`and
`html
Slide
`$3
It's needed to set it to
true and to set the content in the dot for every slide using the @Input property dotContent:`html
Slide 1
`- in the case when
content is the prop of a component.`html
Slide 1
`- in the case when
content is simple text.The ontent can be simple text or the HTML-markup. Dots with this option work as tabs. The option
items should be set to 1, otherwise, scrolling of slides will be done by pages (1 page equals the number of visible slides).
If the dotContent isn't provided in , its values will be '' (this is the default value).$3
When there's the option
slideBy='page', disabled prev or next buttons will rewind the carousel to the start or the end accordingly.
When the number of pages (dots) is 2 and there's the option loop=false, changing pages could cause thoughts something is wrong (when the carousel is on the first page, click on the prev button makes the carousel show the second page which is the ending of the carousel at the same time; in this case the next and prev button do the same job). To avoid this behavior, the number of pages must be 3 and more or it's needed to set loop=true.The number of pages depends on the number of all slides and the option
items (e.g. if the quantity of slides is 10 and items=3, the number of pages will be 4 (10/3=3.3; 3.3 is rounded to 4)).$3
The documentation of Owl Carousel says the default value of this option is set to
true, but the code defines it as false. In ngx-owl-carousel-o, its default value is set to false.WARNING: options
rewind and loop shouldn't be enabled in one carousel. They do a similar job in different ways.$3
The option
freeDrag doesn't have the realization. Thus setting it to true will give nothing. This option doesn't work even in Owl Carousel written by means of jQuery.$3
The option
autoplayTimeout must always be bigger than the option autoplaySpeed. Otherwise, the autoplay won't work.$3
This options works just in the case
autoplayHoverPause is enabled. autoplayMouseleaveTimeout sets the value of just the first timeout after firing the event mouseleave. Default meaning is 1. Then the value of autoplayTimeout is applied.$3
When the option
URLhashListener=true, it's required to define the @Input prop dataHash in :`html
Slide 1
Slide 2
` or
`html
Slide 1
Slide 2
`where
hashObj is the object with hashes (fragments) of url. hashObj could be an array. Defining the kind of data store is up to the developer.NOTE:
HashService uses services ActivatedRoute and Router for making it possible to navigate by hashes (fragments). And if RouterModule.forRoot(routes) isn't imported in the main module of an application, the problem will appear. HashService won't work. Therefore it's needed to import RouterModule.forRoot(routes) in the main module of an application even in the case of creating the simple app for testing the work of the library.$3
There's no need to set to
attributes data-src and data-src-retina because Angular has its own realization for . In Angular it's better to write . src is the data-binding, which means Angular will set the value to the native attribute src of after loading its core code. Original Owl Carousel reads data-src and sets the native attribute src at needed moment. Of course, ngx-owl-carousel-o has additional tricks for lazy loading images (better to say the content of slides) put into slides.$3
By default, this option is set to
false. This option changes the number of visible slides in the case, when the number of slides is less than the value of the option items. For example, when the items=4 and there're just 3 slides, the carousel will reassign the value of items to 3.When the option
skip_validateItems is true, the carousel won't reassign the items. So, in the example above items will remain 4. But there will be 3 slides and one empty place. This for the case when the option loop=false. When loop=true, the empty place will be populated by the copy of the first slide.Refreshing the carousel if options change
The code can detect different options and rerender the carousel. But the comparison of previous options and new options is shallow:
prevOptions === newOptions.It means that mutating options object won't trigger the carousel refreshing:
`typescript
// ...
customOptions: OwlOptions = {
autoWidth: true,
loop: true,
// ....
} changeOptions() {
this.customOptions.loop = false; // this won't refresh the carousel
}
`It's needed to create a new options object. The object destructuring is helpful here (Note it works if you still use Zone.js):
`typescript
// ...
customOptions: OwlOptions = {
autoWidth: true,
loop: true,
// ....
} changeOptions() {
this.customOptions = { ...this.customOptions, loop: false } // this will make the carousel refresh
}
`For projects with no Zone.js, you should use signals and do this:
`typescript
// ...
customOptions = signal({
autoWidth: true,
loop: true,
// ....
}) changeOptions() {
this.customOptions.update((cur) => ({
...cur,
loop: !cur.loop,
responsive: {
0: {
items: 1
},
600: {
items: 2
},
900: {
items: 2
}
},
})); // this will make the carousel refresh
}
`owlRouterLink
The directive
owlRouterLink is introduced for making impossible the navigating between components while the carousel is dragging.This directive has the same features as the native
routerLink directive. One exception is the property stopLink. It prevents the navigating to another component.This directive is included into
CarouselModule, which must be imported into a needed module before using the ngx-owl-carousel-o. So, to use this directive, you just need to write it inside the needed slide.Example of usage this directive:
`html
@for (item of slidesStore(); track item.id) {
}
`{{item.text}} contains owlRouterLink directive and its @Input property stopLink.{{item.text}} is also possible way of using this directive.In the example above, we see the usage of
dragging event, owlRouterLink, and stopLink.
When the dragging of the carousel starts, the dragging event notifies about it by passing object` typescript
{
dragging: true,
data: {}
}
`The value of the prop
dragging is assigned to the isDraggable property. Then this property is passed into owlRouterLink through stopLink. Directive gets aware of dragging the carousel and prevents any navigations.When the dragging of the carousel is finished,
dragging passes object` typescript
{
dragging: false,
data: {}
}
`
isDraggable gets updated, which causes the change of stopLink. Now its value is false. This enables navigating during the next simple click on locating in the slide unless new dragging starts.So, to use
in any slide, it's recommended to:- use
dragging event and property isDragging (or named differently);
- use owlRouterLink directive;
- use stopLink property of owlRouterLink. It's needed to pass to this prop isDragging. Using of stopLink is required.The real example is here.
The
has the automatic preventing navigation during dragging.Events
- translated.
- dragging.
- change.
- changed.
- initialized.
$3
It fires after the carousel finishes translating and exposes the object of the type
SlidesOutputData.`typecript
class SlidesOutputData {
startPosition?: number;
slides?: SlideModel[];
};
`startPosition is the position of the first slide with the class .activeslides is the array with data of each active slide. Data of each active slide are:`typescript
{
id: string; // id of slide
width: number; // width of slide
marginL: number; // margin-left of slide
marginR: number; // margin-right of slide
center: boolean; // whether slide is centered (has .center)
}
`The code for subscribing to this event is the following:
CarouselHolderComponent`typescript
import { SlidesOutputData, OwlOptions } from 'ngx-owl-carousel-o';
@Component({
selector: '....',
template: @for (slide of slidesStore; track slide.id) {
}
})
export class CarouselHolderComponent {
customOptions: OwlOptions = {
loop: true,
mouseDrag: false,
touchDrag: false,
pullDrag: false,
dots: false,
navSpeed: 700,
navText: ['', ''],
responsive: {
0: {
items: 1
},
400: {
items: 2
},
740: {
items: 3
},
940: {
items: 4
}
},
nav: true
} activeSlides: SlidesOutputData;
slidesStore: any[];
constructor() {}
getPassedData(data: SlidesOutputData) {
this.activeSlides = data;
console.log(this.activeSlides);
}
}
`(translated)="getPassedData($event)" is the subscription or attaching to the event;getPassedData(data: SlidesOutputData) is the method which takes data about active slides.activeSlides is the property of CarouselHolderComponent, which stores data about active slides$3
The event
dragging fires after that the user starts dragging the carousel. It exposes the object` typescript
{
dragging: boolean,
data: SlidesOutputData
}class SlidesOutputData {
startPosition?: number;
slides?: SlideModel[];
};
`When the dragging of the carousel is started its paylod is:
` typescript
{
dragging: true,
data: {
startPosition: 0,
slides: [ slide, slide, slide ];
}
}
`The prop
data shows the situation which was at the moment of starting dragging. In other words, if before dragging the carousel the prop startPosition was 0, the event dragging will emit this prop with the same value.When the dragging of the carousel is finished and the event
translated is fired dragging fires again but its payload has value` typescript
{
dragging: false,
data: {
startPosition: 1,
slides: [ slide, slide, slide ];
}
}
`This time, the prop
data shows current startPosition and current active slides.This event is needed for the cases when slide should contain the tag
with the routerLink directive.Example of using this event:
`html
@for (item of carouselData; track item.id) {
`
(dragging)="isDragging = $event.dragging" This expression uses the dragging event and has the property isDragging which should be created in the component hosting the .
$event is the payload of the event. Its prop dragging can be true or false.
The real example is here.
It fires after the carousel gets initialized and exposes the object of the type SlidesOutputData.
`typecript`
class SlidesOutputData {
startPosition?: number;
slides?: SlideModel[];
};
startPosition is the position of the first slide with the class .active
slides is the array with data of each active slide. Data of each active slide are:
`typescript`
{
id: string; // id of slide
width: number; // width of slide
marginL: number; // margin-left of slide
marginR: number; // margin-right of slide
center: boolean; // whether slide is centered (has .center)
}
The code for subscribing to this event is the following:
CarouselHolderComponent
`typescript
import { SlidesOutputData, OwlOptions } from 'ngx-owl-carousel-o';
@Component({
selector: '....',
template:
@for (slide of slidesStore; track slide.id) {
}
})
export class CarouselHolderComponent {
customOptions: OwlOptions = {
loop: true,
mouseDrag: false,
touchDrag: false,
pullDrag: false,
dots: false,
navSpeed: 700,
navText: ['', ''],
responsive: {
0: {
items: 1
},
400: {
items: 2
},
740: {
items: 3
},
940: {
items: 4
}
},
nav: true
}
activeSlides: SlidesOutputData;
slidesStore: any[];
constructor() {}
getData(data: SlidesOutputData) {
this.activeSlides = data;
console.log(this.activeSlides);
}
}
`
(initialized)="getData($event)" is the subscription or attaching to the event;
getData(data: SlidesOutputData) is the method which takes data about active slides.
activeSlides is the property of CarouselHolderComponent, which stores data about active slides
It fires after each change in the carousel (click on dots, nav buttons). However, while the user drags the carousel this event fires after dropping the carousel or after stopping dragging.
This event exposes the object of the type SlidesOutputData. It's populated by data defined before firing the event. This event just notifies about changes. New data (active slides, startPosition) gets available after the end of moving the carousel (event translated).
`typescript`
class SlidesOutputData {
startPosition?: number;
slides?: SlideModel[];
};
startPosition is the position of the first slide with the class .active
slides is the array with data of each active slide. Data of each active slide are:
`typescript`
{
id: string; // id of slide
width: number; // width of slide
marginL: number; // margin-left of slide
marginR: number; // margin-right of slide
center: boolean; // whether slide is centered (has .center)
}
The code for subscribing to this event is the following:
CarouselHolderComponent
`typescript
import { SlidesOutputData, OwlOptions } from 'ngx-owl-carousel-o';
@Component({
selector: '....',
template:
@for (slide of slidesStore; track slide.id) {
}
})
export class CarouselHolderComponent {
customOptions: OwlOptions = {
loop: true,
mouseDrag: false,
touchDrag: false,
pullDrag: false,
dots: false,
navSpeed: 700,
navText: ['', ''],
responsive: {
0: {
items: 1
},
400: {
items: 2
},
740: {
items: 3
},
940: {
items: 4
}
},
nav: true
}
activeSlides: SlidesOutputData;
slidesStore: any[];
constructor() {}
getData(data: SlidesOutputData) {
this.activeSlides = data;
console.log(this.activeSlides);
}
}
`
(change)="getData($event)" is the subscription or attaching to the event;
getData(data: SlidesOutputData) is the method which takes data about active slides.
activeSlides is the property of CarouselHolderComponent, which stores data about active slides
It fires when user clicks dots or nav buttons and new data about active slides becomes known. This event fires before the event translated gets fired. However, while the user drags the carousel this event fires after dropping the carousel or after stopping dragging.SlidesOutputData
This event exposes the object of the type :
`typescript`
class SlidesOutputData {
startPosition?: number;
slides?: SlideModel[];
};
startPosition is the position of the first slide with the class .active
slides is the array with data of each active slide. Data of each active slide are:
`typescript`
{
id: string; // id of slide
width: number; // width of slide
marginL: number; // margin-left of slide
marginR: number; // margin-right of slide
center: boolean; // whether slide is centered (has .center)
}
The code for subscribing to this event is the following:
CarouselHolderComponent
`typescript
import { SlidesOutputData, OwlOptions } from 'ngx-owl-carousel-o';
@Component({
selector: '....',
template:
@for (slide of slidesStore; track slide.id) {
}
})
export class CarouselHolderComponent {
customOptions: OwlOptions = {
loop: true,
mouseDrag: false,
touchDrag: false,
pullDrag: false,
dots: false,
navSpeed: 700,
navText: ['', ''],
responsive: {
0: {
items: 1
},
400: {
items: 2
},
740: {
items: 3
},
940: {
items: 4
}
},
nav: true
}
activeSlides: SlidesOutputData;
slidesStore: any[];
constructor() {}
getData(data: SlidesOutputData) {
this.activeSlides = data;
console.log(this.activeSlides);
}
}
`
(changed)="getData($event)" is the subscription or attaching to the event;
getData(data: SlidesOutputData) is the method which takes data about active slides.
activeSlides is the property of CarouselHolderComponent, which stores data about active slides
ngx-owl-carousel-o has almost all plugins written on the page Owl Carousel Plugin API except the VideoPlugin.
This plugin isn't realized. In order to play the video, use special packages (e.g. ngx-embed-video; ngx-youtube-player and so on).
It's better to create special component with the video and put it in
The example:
`html`
id and url are data-binding properties, defined in the component which contains .
Some examples of using this lib are displayed in the app demo-owl-carousel:
- The carousel with autoWidth=true. Typescript part and HTML partautoHeight=true
- The carousel with , URLhashListener=true and startPosition='URLHash'. Typescript part and HTML partautoplay=true
- The carousel with . Typescript part and HTML part
NOTE: demo-owl-carousel could be downloaded and started on own PC. Steps for achieving that are:
- git clone https://github.com/vitalii-andriiovskyi/ngx-owl-carousel-o.git;yarn
- or npm install;ng serve
- or ng serve --project=demo-owl-carousel.
Also, lots of variants of using carousel are in files carousel.component.spec.ts and stage.component.spec.ts.
They contain tests of the library. These tests include many functions it(). The example:
`typescript
it('should change height of carousel [options]="{nav: true, autoHeight: true}"', fakeAsync(() => {
discardPeriodicTasks();
const html =
Slide 1
Slide 2
Slide 3
Slide 4
Slide 5
;
fixtureHost = createTestComponent(html);
deCarouselComponent = fixtureHost.debugElement.query(By.css('owl-carousel-o'));
tick();
fixtureHost.detectChanges();
// some code ...
}));`The first argument of
it() explains how the carousel should work with options written in const html=.... In this example the height of the carousel should change automatically: should change height of carousel [options]="{nav: true, autoHeight: true}".Variable
html contains the HTML-markup of the carousel for [options]="{nav: true, autoHeight: true}".However, most of the HTML-markups set to
html are simplified. There's no property customOptions, directive *ngFor and as it is in examples above.$3
It's possible to move the carousel left/right and to needed slide from different places of the html-page. The real is provided in home.component.html
`html
@for (item of carouselData; track item.id) {
}
`Key points are:
1. Defining in
template reference variable #owlCar.
2. Using it in handlers for events. In the code above, we see (click)="owlCar.prev()", (click)="owlCar.next()" and (click)="owlCar.to('slide-3')". #owlCar could be passed as an argument of the hanlder: (click)="handler(owlCar).
- owlCar.prev() shows the previous slide.
- owlCar.next() shows the next slide.
- owlCar.to('slide-3') moves the carousel to the slide with needed id. In this case slide-3 is the needed slide. NOTE: it's needed to supply own ids to slides. The code above has [id]="item.id". This is the way of supplying ids.ReferenceError: Event is not defined
The details of the issue are following:
`text
$ yarn serve:ssr
yarn run v1.17.3
$ node dist/server
D:\WEB-learning\Angular\projects-libs\owl-carousel\owl-carousel-test-for-built-lib\test-project\owl-carousel-o-demo-ng8\dist\ser
ver\main.js:87252
Object(tslib__WEBPACK_IMPORTED_MODULE_0__["__metadata"])("design:paramtypes", [Event]),
^ReferenceError: Event is not defined
at Module.KMir (D:\WEB-learning\Angular\projects-libs\owl-carousel\owl-carousel-test-for-built-lib\test-project\owl-carousel
-o-demo-ng8\dist\server\main.js:87252:84)
at __webpack_require__ (D:\WEB-learning\Angular\projects-libs\owl-carousel\owl-carousel-test-for-built-lib\test-project\owl-
carousel-o-demo-ng8\dist\server\main.js:20:30)
at Object.F+o+ (D:\WEB-learning\Angular\projects-libs\owl-carousel\owl-carousel-test-for-built-lib\test-project\owl-carousel
-o-demo-ng8\dist\server\main.js:79718:12)
at __webpack_require__ (D:\WEB-learning\Angular\projects-libs\owl-carousel\owl-carousel-test-for-built-lib\test-project\owl-
carousel-o-demo-ng8\dist\server\main.js:20:30)
at Object.V7fC (D:\WEB-learning\Angular\projects-libs\owl-carousel\owl-carousel-test-for-built-lib\test-project\owl-carousel
-o-demo-ng8\dist\server\main.js:99395:12)
at __webpack_require__ (D:\WEB-learning\Angular\projects-libs\owl-carousel\owl-carousel-test-for-built-lib\test-project\owl-
carousel-o-demo-ng8\dist\server\main.js:20:30)
at Object.K011 (D:\WEB-learning\Angular\projects-libs\owl-carousel\owl-carousel-test-for-built-lib\test-project\owl-carousel
demo-ng8\dist\server\main.js:92:18) at __webpack_require__ (D:\WEB-learning\Angular\projects-libs\owl-carousel\owl-carousel-test-for-built-lib\test-project\owl-
carousel-o-demo-ng8\dist\server\main.js:20:30)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
`The issue
`text
Object(tslib__WEBPACK_IMPORTED_MODULE_0__["__metadata"])("design:paramtypes", [Event]),
^ReferenceError: Event is not defined
`is connected with decorator
@HostListener. In the case of ngx-owl-carousel-o, it emerges just in Angular 8.$3
server.ts:` typescript
import * as express from 'express';
import {join} from 'path';// -----------------------------------------------------------------------------------
import { readFileSync } from 'fs'; // import readFileSync (1)
const domino = require('domino'); // import the library
domino (2)
// -----------------------------------------------------------------------------------const app = express();
const PORT = process.env.PORT || 4000;
const DIST_FOLDER = join(process.cwd(), 'dist/browser');
// -----------------------------------------------------------------------------------
const template = readFileSync(join(DIST_FOLDER, 'index.html')).toString(); // use
index.html as template (3)
const win = domino.createWindow(template); // create object Window (4)
global['Event'] = win.Event; // assign the win.Event to prop Event (5)
// -----------------------------------------------------------------------------------// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const {AppServerModuleNgFactory, LAZY_MODULE_MAP, ngExpressEngine, provideModuleMap} = require('./dist/server/main');
`This solution is taken from https://github.com/hippee-lee/3940-v8-ssr/blob/master/server.ts#L29
$3
server/app.module.ts`typescript
const BROWSER_DIR = join(process.cwd(), 'dist/browser');
applyDomino(global, join(BROWSER_DIR, 'index.html'));
global['Event'] = global['window']['Event']; // define the global property Event
`Using Internal Slide Data
It's possible to use internal slide data for own purposes. But this data is exposed in version
5.1.0 and higher.The slide data structure:
`typescript
class SlideModel { /**
* Id of slide
*/
id: string;
/**
* Active state of slide. If true slide gets css-class .active
*/
isActive?: boolean;
/**
* Number of grid parts to be used
*/
dataMerge?: number;
/**
* Width of slide
*/
width?: number | string;
/**
* Css-rule 'margin-left'
*/
marginL?: number | string;
/**
* Css-rule 'margin-right'
*/
marginR?: number | string;
/**
* Make slide to be on center of the carousel
*/
isCentered?: boolean;
/**
* Mark slide to be on center of the carousel (has .center)
*/
center?: boolean;
/**
* Cloned slide. It's being used when 'loop'=true
*/
isCloned?: boolean;
/**
* Indicates whether slide should be lazy loaded
*/
load?: boolean;
/**
* Css-rule 'left'
*/
left?: number | string;
/**
* Changeable classes of slide
*/
classes?: {[key:string]: boolean};
/**
* Shows whether slide could be animated and could have css-class '.animated'
*/
isAnimated?: boolean;
/**
* Shows whether slide could be animated-in and could have css-class '.owl-animated-in'
*/
isDefAnimatedIn?: boolean;
/**
* Shows whether slide could be animated-out and could have css-class '.owl-animated-out'
*/
isDefAnimatedOut?: boolean;
/**
* Shows whether slide could be animated-in and could have animation css-class defined by user
*/
isCustomAnimatedIn?: boolean;
/**
* Shows whether slide could be animated-out and could have animation css-class defined by user
*/
isCustomAnimatedOut?: boolean;
/**
* State for defining the height of slide.It's values could be 'full' and 'nulled'. 'Full' sets css-height to 'auto', 'nulled' sets height to '0'.
*/
heightState?: string;
/**
* Hash (fragment) of url which corresponds to slide
*/
hashFragment?: string;
}
`To get this data, define the variable
let-owlItem or let-slideData in your template (the name of a variable could be any):`html
`An internal slide data could be very helpful to add cool animations using native CSS animations. Use properties
isActive and isCentered to toggle a CSS class. An example is below.1. Define animation in
your.component.ts:
`typescript
@Component({
selector: 'app-test',
templateUrl: './test.component.html',
// CSS animation is defined in the .slide, .slide.active classes. Check rules transform, opacity, and transition
styles: [ .wrapper {
max-width: 800px;
margin: 0 auto;
}
]
})
export class TestComponent implements OnInit {
// .....
customOptions: OwlOptions = {
loop: true,
dots: false,
navSpeed: 700,
navText: ['<<', '>>'],
center: true, // most important for this example
responsive: {
0: {
items: 1
},
740: {
items: 3
}
},
nav: true
}
}
`
2. Use internal slide data in the template. This example uses let-owlItem and prop isCentered (owlItem.isCentered) to toggle CSS class .active:
test.component.html
`html`
@for (image of imagesData; track image.id) {
}
doesn't stay paused when user opens mat-menuThis issue appears even in the case when the option autoplayHoverPause is set to true. This is because the carousel listens to the events mouseover and mouseleave. When a user opens mat-menu, the code adds overlay, what triggers mouseleave. ngx-owl-carousel-o renews autoplaying after this event is fired.
The solution for this case is to manage autoplaying manually. You can do that using two methods of CarouselComponent: stopAutoplay and startAutoplay.
Example of usage in a template with mat-menu:
`html`
@for (item of carouselData; let i = $index; track item.id) {
}
When menu is opened, you call stopAutoplay: (menuOpened)="owlCar.stopAutoplay()" startAutoplay
When menu is closed, you call : (closed)="owlCar.startAutoplay()"
_Important_:
Inactive slides should be hidden from screen readers. To achieve that, the logic sets the option ariaHidden to true. But if you have focusable elements inside inactive slides, you should set ariaHidden to false and tabindex to -1 for these elements as well. Otherwise, a user pressing Tab key will be able to focus these elements in inactive slides and be confused with this.
The logic for accessibility covers these scenarios:
- A user presses tab when any tabbable element before the carousel is focused to move the focus to the first focusable element in the carousel
This could be the prev button, unless it is disabled at the moment, or the next button if the prev button is disabled.
- If both nav buttons are enabled a user should be able to move focus between prev and next buttons using arrowLeft and arrowRight keys
- If the focus is on the next button and a user presses tab, the focus should move to the active dot.
- If a user wants to focus another dot to click (press) it to change a slide, one should use arrowLeft and arrowRight keys to move focus between dots.
- If a dot is focused and a user presses the Tab key, the focus should move to the first tabbable element after carousel.
- If a user presses Shift+Tab then the focus moves back to the dot that was focused before tabbing out of carousel.Shift+Tab
- If a user presses again, the focus should move to next nav button.Shift+Tab` again, the focus should move to an active slide if it has a focusable element, or prev button if it's not disabled,
- If a user presses
or the last tabbable element before carousel.
This project is licensed under the terms of the MIT License