vitalii-andriiovskyi / ngx-owl-carousel-o

owl-carousel for Angular >=6
MIT License
178 stars 51 forks source link

ngx-owl-carousel-o

Compatibility

ngx-owl-carousel-o Angular
18.x.x 18.x.x
17.x.x (latest 17.0.0) 17.x.x
16.x.x (latest 16.0.0) 16.x.x
15.x.x (latest 15.0.1) 15.x.x
14.x.x (latest 14.0.1) 14.x.x
7.x.x (latest 7.0.4) 13.x.x
6.x.x (latest 6.0.2) 12.x.x
5.x.x (latest 5.1.1) 11.x.x
4.x.x (latest 4.1.1) 10.x.x
3.x.x (latest 3.1.1) 9.x.x
2.x.x (latest 2.1.1) 8.x.x
1.x.x (latest 1.2.1) 7.x.x
0.x.x (latest 0.1.2) 6.x.x

CHANGELOG

Table of Contents

Get started

  1. Run yarn add ngx-owl-carousel-o or npm install ngx-owl-carousel-o.

  2. Add styles (one of these variants).

    • angular.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:

      @import 'ngx-owl-carousel-o/lib/styles/scss/owl.carousel';
      @import 'ngx-owl-carousel-o/lib/styles/scss/owl.theme.default';
  3. Import RouterModule and Routes into AppModule unless they are imported.

  4. Import BrowserAnimationsModule into AppModule unless it is imported.

  5. Import CarouselModule into a module which declares a component intended to have a carousel.

    import { CarouselModule } from 'ngx-owl-carousel-o';
    @NgModule({
      imports: [ CarouselModule ],
      declarations: [ CarouselHolderComponent ]
    })
    export class SomeModule { }
  6. Add to needed component customOptions or named in different way object with options for the carousel:

    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
      }
    }
  7. Add html-markup to the template of the component (in this case, add it to carousel-holder.component.html):

      <div>Some tags before</div>
      <owl-carousel-o [options]="customOptions">
        <ng-template carouselSlide>Slide 1</ng-template>  
        <ng-template carouselSlide>Slide 2</ng-template>  
        <ng-template carouselSlide>Slide 3</ng-template>  
      </owl-carousel-o>
      <div>Some tags after</div>

    or

      <div>Some tags before</div>
      <owl-carousel-o [options]="customOptions">
    
        <ng-container *ngFor="let slide of slidesStore">
          <ng-template carouselSlide [id]="slide.id">
            <img [src]="slide.src" [alt]="slide.alt" [title]="slide.title">
          </ng-template>
        </ng-container>
    
      </owl-carousel-o>
      <div>Some tags after</div>

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:

    "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:

  <div>Some tags before</div>
  <owl-carousel-o [options]="customOptions">

    <ng-container *ngFor="let slide of slidesStore">
      <ng-template carouselSlide [id]="slide.id">
        <img [src]="slide.src" [alt]="slide.alt" [title]="slide.title">
      </ng-template>
    </ng-container>

  </owl-carousel-o>
  <div>Some tags after</div>

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

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 <ng-template[carouselSlide]> directive. The way of setting it is:

<ng-template carouselSlide [dataMerge]="number">Slide text or HTML markup</ng-template>

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).

autoWidth

The option autoWidth=true is working if user sets the @Input prop width to <ng-template[carouselSlide]> directive. The example:

<ng-template carouselSlide [width]="number">Slide text or html markup</ng-template>

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.

responsiveBaseElement

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 <div class="owl-carousel"> which takes 100% of its parent element width.

fallbackEasing

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.

info

Option info doesn't work.

navElement, navContainer, navContainerClass, navClass, dotContainer, dotClass and dotsClass

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

nestedItemSelector

The option nestedItemSelector doesn't work.

itemElement, itemClass, stageElement, stageOuterClass, stageClass, refreshClass, loadedClass, loadingClass, rtlClass, responsiveClass, dragClass and grabClass

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

navText

NOTE: Setting options in the HTML-template in the way like

<owl-carousel-o [options]="{navText: [ '<i class="fa-chevron-left"></i>', '<i class="fa-chevron-right></i>"' ]}">
  <ng-template carouselSlide>Slide</ng-template>
</owl-carousel-o>

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.

customOptions: OwlOptions = {
 navText: [ '<i class="fa-chevron-left"></i>', '<i class="fa-chevron-right></i>"' ]
}

and

<owl-carousel-o [options]="customOptions">
  <ng-template carouselSlide>Slide</ng-template>
</owl-carousel-o>

dotsData

It's needed to set it to true and to set the content in the dot for every slide using the @Input property dotContent:

<ng-template carouselSlide [dotContent]="content">Slide 1</ng-template>
<ng-template carouselSlide dotContent="content">Slide 1</ng-template>

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 <ng-template [carouselSlide]>, its values will be '' (this is the default value).

slideBy

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)).

rewind

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.

freeDrag

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.

autoplayTimeout and autoplaySpeed

The option autoplayTimeout must always be bigger than the option autoplaySpeed. Otherwise, the autoplay won't work.

autoplayMouseleaveTimeout

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.

URLhashListener

When the option URLhashListener=true, it's required to define the @Input prop dataHash in <ng-template carouselSlide>:

<ng-template carouselSlide id="owl-slide-1" dataHash="one"><div>Slide 1</div></ng-template>
<ng-template carouselSlide id="owl-slide-2" dataHash="two"><div>Slide 2</div></ng-template>

 or

<ng-template carouselSlide id="owl-slide-1" [dataHash]="hashObj.one"><div>Slide 1</div></ng-template>
<ng-template carouselSlide id="owl-slide-2" [dataHash]="hashObj.two"><div>Slide 2</div></ng-template>

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 case the of creating the simple app for testing the work of the library.

lazyLoad

There's no need to set to <img> attributes data-src and data-src-retina because Angular has its own realization for <img>. In Angular it's better to write <img [src]="someURL">. src is the data-binding, which means Angular will set the value to the native attribute src of <img> 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.

skip_validateItems

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:

  // ...
  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:

  // ...
  customOptions: OwlOptions = {
    autoWidth: true,
    loop: true,
    // ....
  }

  changeOptions() {
    this.customOptions = { ...this.customOptions, loop: false } // 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:

  <owl-carousel-o [options]="customOptions" (dragging)="isDragging = $event.dragging">

    <ng-container *ngFor="let item of carouselData">
      <ng-template carouselSlide>
        <div class="slider">
          <a [owlRouterLink]="['/present']" [stopLink]="isDragging">{{item.text}}</a>
          <a class="outer-link" href="https://www.google.com">
            <span>{{item.text}}</span>
          </a>

        </div>
      </ng-template>
    </ng-container>

  </owl-carousel-o>

<a [owlRouterLink]="['/present']" [stopLink]="isDragging">{{item.text}}</a> contains owlRouterLink directive and its @Input property stopLink.

<a owlRouterLink="'/present'" [stopLink]="isDragging">{{item.text}}</a> 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

{
  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

{
  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 <a> locating in the slide unless new dragging starts.

So, to use <a> in any slide, it's recommended to:

The real example is here.

The <a href="https://github.com/vitalii-andriiovskyi/ngx-owl-carousel-o/blob/develop/someUrl"> has the automatic preventing navigation during dragging.

Events

translated

It fires after the carousel finishes translating and exposes the object of the type SlidesOutputData.

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:

{
  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

import { SlidesOutputData, OwlOptions } from 'ngx-owl-carousel-o';
@Component({
      selector: '....',
      template: `
      <owl-carousel-o [options]="customOptions" (translated)="getPassedData($event)">

        <ng-container *ngFor="let slide of slidesStore">
          <ng-template carouselSlide [id]="slide.id">
            <img [src]="slide.src" [alt]="slide.alt" [title]="slide.title">
          </ng-template>
        </ng-container>

      </owl-carousel-o>
    `
    })
    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

dragging

The event dragging fires after that the user starts dragging the carousel. It exposes the object

{
  dragging: boolean,
  data: SlidesOutputData
}

class SlidesOutputData {
  startPosition?: number;
  slides?: SlideModel[];
};

When the dragging of the carousel is started its paylod is:

{
  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

{
  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 <a> with the routerLink directive.

Example of using this event:

  <owl-carousel-o [options]="customOptions" (dragging)="isDragging = $event.dragging">

    <ng-container *ngFor="let item of carouselData">
      <ng-template carouselSlide>

        <div class="slider">
          <a [owlRouterLink]="['/present']" [stopLink]="isDragging">{{item.text}}</a>
          <a class="outer-link" href="https://www.google.com">
            <span>{{item.text}}</span>
          </a>

        </div>
      </ng-template>
    </ng-container>

  </owl-carousel-o>

(dragging)="isDragging = $event.dragging" This expression uses the dragging event and has the property isDragging which should be created in the component hosting the <ngx-owl-carousel-o>.

$event is the payload of the event. Its prop dragging can be true or false. The real example is here.

initialized

It fires after the carousel gets initialized and exposes the object of the type SlidesOutputData.

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:

{
  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

import { SlidesOutputData, OwlOptions } from 'ngx-owl-carousel-o';
@Component({
      selector: '....',
      template: `
      <owl-carousel-o [options]="customOptions" (initialized)="getData($event)">

        <ng-container *ngFor="let slide of slidesStore">
          <ng-template carouselSlide [id]="slide.id">
            <img [src]="slide.src" [alt]="slide.alt" [title]="slide.title">
          </ng-template>
        </ng-container>

      </owl-carousel-o>
    `
    })
    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

change

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).

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:

{
  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

import { SlidesOutputData, OwlOptions } from 'ngx-owl-carousel-o';
@Component({
      selector: '....',
      template: `
      <owl-carousel-o [options]="customOptions" (change)="getData($event)">

        <ng-container *ngFor="let slide of slidesStore">
          <ng-template carouselSlide [id]="slide.id">
            <img [src]="slide.src" [alt]="slide.alt" [title]="slide.title">
          </ng-template>
        </ng-container>

      </owl-carousel-o>
    `
    })
    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

changed

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. This event exposes the object of the type SlidesOutputData:

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:

{
  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

import { SlidesOutputData, OwlOptions } from 'ngx-owl-carousel-o';
@Component({
      selector: '....',
      template: `
      <owl-carousel-o [options]="customOptions" (changed)="getData($event)">

        <ng-container *ngFor="let slide of slidesStore">
          <ng-template carouselSlide [id]="slide.id">
            <img [src]="slide.src" [alt]="slide.alt" [title]="slide.title">
          </ng-template>
        </ng-container>

      </owl-carousel-o>
    `
    })
    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

Plugins

ngx-owl-carousel-o has almost all plugins written on the page Owl Carousel Plugin API except the VideoPlugin.

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 <ng-template carouselSlide>....</ng-template> The example:

<ng-template carouselSlide [dotContent]="content">
    <custom-video [id]="videoId" [url]="someURL" (someEvent)="handlerOfSomeEvent"></custom-video>
</ng-template>

id and url are data-binding properties, defined in the component which contains <owl-carousel-o>.

Tips

Real examples to help

Some examples of using this lib are displayed in the app demo-owl-carousel:

NOTE: demo-owl-carousel could be downloaded and started on own PC. Steps for achieving that are:

Tests to help

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:

it('should change height of carousel [options]="{nav: true, autoHeight: true}"', fakeAsync(() => {
    discardPeriodicTasks();
    const html = `
      <div style="width: 920px; margin: auto">

        <owl-carousel-o [options]="{nav: true, autoHeight: true}">

          <ng-template carouselSlide id="owl-slide-1">
            <div style="height: 100px">Slide 1</div>
          </ng-template>

          <ng-template carouselSlide id="owl-slide-2">
            <div style="height: 40px">Slide 2</div>
          </ng-template>

          <ng-template carouselSlide id="owl-slide-3">
            <div style="height: 80px">Slide 3</div>
          </ng-template>

          <ng-template carouselSlide id="owl-slide-4">
            <div style="height: 130px">Slide 4</div>
          </ng-template>

          <ng-template carouselSlide id="owl-slide-5">
            <div style="height: 90px">Slide 5</div>
          </ng-template>

        </owl-carousel-o>

      </div>
    `;
    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 <ng-container> as it is in examples above.

Managing the carousel from outside its markup

It's possible to move the carousel left/right and to needed slide from different places of the html-page. The real example is provided in home.component.html

<owl-carousel-o [options]="customOptions" (translated)="getPassedData($event)" #owlCar>

  <ng-container *ngFor="let item of carouselData">
    <ng-template carouselSlide [id]="item.id" [width]="item.width">
      <div class="slider">
        <p>{{item.text}}</p>

      </div><!-- /.carousel-item team-member -->
    </ng-template>
  </ng-container>

</owl-carousel-o>

<p>
  <a class="btn btn-success" (click)="owlCar.prev()">prev</a> <==>
  <a class="btn btn-success" (click)="owlCar.next()">next</a>
</p>
<p><a class="btn btn-success" (click)="owlCar.to('slide-3')">move to 3th slide</a></p>

Key points are:

  1. Defining in <owl-carousel-o> 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:

$ 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

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.

The solution for the express.js (pay attention to comments)

server.ts:

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

The solution for the NestJs (pay attention to comments)

server/app.module.ts

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:

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):

  <ng-template carouselSlide let-owlItem>
    <div class="slide">
      {{owlItem.isActive}}
      {{owlItem.isCentered}}
      <img [src]="image.src" [alt]="image.alt" [title]="image.title">
    </div>
  </ng-template>

An internal slide data could be very helpful to add cool Angular animations. Use properties isActive and isCentered to switch the state of animation. An example is below.

  1. Define animation in your.component.ts:

    @Component({
      selector: 'app-test',
      templateUrl: './test.component.html',
    
      // .....
      animations: [
        trigger('activeSlide', [
          state('active', style({
            transform: 'scale(1.4)',
            opacity: 1,
          })),
          state('inActive', style({
            transform: 'scale(0.7)',
            opacity: 0.8,
          })),
          transition('active => inActive', [
            animate('0.5s')
          ]),
          transition('inActive => active', [
            animate('0.5s')
          ])
        ])
      ]
    })
    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 animation state:

    test.component.html

      <owl-carousel-o [options]="customOptions" #owlCat>
        <ng-container *ngFor="let image of imagesData">
          <ng-template carouselSlide let-owlItem> 
            <!--                                 \/          -->
            <div class="slide" [@activeSlide]="owlItem.isCentered ? 'active' : 'inActive'">
              <img [src]="image.src" [alt]="image.alt" [title]="image.title">
            </div>
          </ng-template>
        </ng-container>
      </owl-carousel-o>

Issue: autoplay doesn't stay paused when user opens mat-menu

This 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:

  <owl-carousel-o [options]="customOptions" (translated)="getPassedData($event)" #owlCar>

    <ng-container *ngFor="let item of carouselData; let i=index">
      <ng-template carouselSlide [width]="item.width">
        <div class="slider">
          <p>{{item.text}}</p>
          <div *ngIf="i == 2">
            <button mat-raised-button color="accent" [matMenuTriggerFor]="menu" (menuOpened)="owlCar.stopAutoplay()">Menu</button>
            <mat-menu #menu="matMenu" (closed)="owlCar.startAutoplay()">
              <button mat-menu-item>Item 1</button>
              <button mat-menu-item>Item 2</button>
              <button mat-menu-item>Item 3</button>
              <button mat-menu-item>Item 4</button>
              <button mat-menu-item>Item 5</button>
            </mat-menu>
          </div>

        </div><!-- /.carousel-item team-member -->
      </ng-template>
    </ng-container>

  </owl-carousel-o>

When menu is opened, you call stopAutoplay: (menuOpened)="owlCar.stopAutoplay()"
When menu is closed, you call startAutoplay: (closed)="owlCar.startAutoplay()"

License

This project is licensed under the terms of the MIT License