1

I have implemented Owl Carousel 2 in my angular2 app with much success until now. The carousel clones items in order to create a loop effect. This is great until you need to perform a click event on the item and the event doesn't fire. There is a work around in the docs, that I found at this SO question. I've modified the JSFiddle from that SO question to show that the workaround works in way that I'm using the carousel in my app. Unfortunately this only solves the problem if your not using Angular 2.

The workaround script is fairly simple:

$('#carousel').on('click', '.item', function () {
     alert("click");
;})

Because of the modular nature of Angular2 and that it discourages direct dom manipulation I can't just throw this in my js files and it works. I have to add it to a component. The question is which component and how do get the dom element refernce of the carousel.

There is a great SO answer here that shows how to use the Owl Carousel with angular2. I modified the Plunker from that question to show how I'm using the carousel in my app and to experiment with ways of solving this problem with the cloned items.

Basically I have 2 Components:

//our root app component
import { Component, AfterViewInit } from 'angular2/core';
import { OwlCarousel } from './owl-carousel.component';

@Component({
  selector: 'app',
  directives: [OwlCarousel],
  template: `

  <div  *ngFor="#carousel of carousels" let i = index;>
  <h3>{{carousel.title}}</h3>
     <owl-carousel [options]="{loop: true, margin: 5}" id=  {{carousel.title}}>
   <div *ngFor="#img of carousel.images">
     <img src="http://lorempixel.com/400/200/{{img.href}}"/>
     <button class='imagebutton'(click)=getImage(img.id) >Select image {{img.id}}</button>
   </div>
   </owl-carousel>
   <button (mouseenter)="over(carousel.title)" (mouseleave)="leave(carousel.title)" id="prev1" class="btn prev">Previous</button>
</div>
`
})

export class App {
 elment: any = {};  
  carousels = [
    {
title: 'caro1',
     images:[
        {id:'1', href: 'sports'},
        {id:'2', href: 'abstract'},
        {id:'3', href: 'people'},
        {id:'4', href: 'transport'},
        {id:'5', href: 'city'},
        {id:'6', href: 'technics'},
        {id:'7', href: 'nightlife'},
        {id:'8', href: 'animals'}
        ]
    }, 
   {
   title: 'caro2',
    images:[
        {id:'1', href: 'food'},
        {id:'2', href: 'cats'},
        {id:'3', href: 'business'},
        {id:'4', href: 'fashion'},
        {id:'5', href: 'nature'},
        {id:'6', href: 'transport'},
        {id:'7', href: 'abstract'},
        {id:'8', href: 'technics'}
        ]
    }
]
intr: any;
owl: any;

getImage(id){
  alert('You selected image' +id);
}

over(title) {
  console.log(title);
        this.intr = setInterval(() => {this.movePrevious(title)}, 500);
    };

 leave(){
      clearInterval(this.intr);
   };    


  movePrevious(title) {
      console.log("elment: " + title);
      this.owl =  $('#'+ title).owlCarousel();
        this.owl.trigger('prev.owl.carousel');
    };

    ngAfterViewInit() { 
        $('#caro1').on('click', '.item .imagebutton', function () {
        alert("click");
  });
    }   
}

You can see there at the bottom in the ngAfterViewInit() I put the workaround code and used the carousel element id to reference it. I'm pretty sure this doesn't work because of the way angular2 works so I tried using angulars ElementRef module (like I do in the code for the owl-carousel component below) but I could not get it to work in that component or the owl-carousel component below.

import { Component, Input, ElementRef, HostBinding } from 'angular2/core';
import $ from 'jquery';
import 'owl-carousel';

@Component({
  selector: 'owl-carousel',
  template: `
  <ng-content></ng-content>  
  `
})
export class OwlCarousel {
  @HostBinding('class') defaultClass = 'owl-carousel';
  @Input() options: object;

  $owlElement: any ={};

  defaultOptions: any = {};

  constructor(private el: ElementRef) {}

  ngAfterViewInit() {

    if(this.options === null){
      this.options = this.defaultOptions
    }
    this.$owlElement = $(this.el.nativeElement).owlCarousel(this.options);

    $(this.el.nativeElement).on('click', '.item .imagebutton', function () {
    alert("click");
    });
  }

  ngOnDestroy() {
    this.$owlElement.data('owlCarousel').destroy();
    this.$owlElement = null;
  }
}

I have tried a few different variations, moving the workaround code between the two components with no success. I even tried .find() like this:

$(this.el.nativeElement).find('#caro1').on('click', '.item .imagebutton', function () {
    alert("click");
    });

Anyone have a clue as to how to implement this workaround for angular2?

Community
  • 1
  • 1
  • I don't see `item` class in your html. Try without `.item` https://plnkr.co/edit/U2mc7CdEkDJcZmESXL2m?p=preview But what are you trying to accompish? – yurzui Jan 21 '17 at 06:35
  • the item class is added by the carousel. When you click on an item in the carousel that has been cloned, the click event doesn't fire. The code snippet workaround will fix that in a standard javascript/jquery frame work. In this case I'm using angular2. I'm trying to figure out how to implement the workaround in angular2. – user3600424 Jan 21 '17 at 19:29
  • Same issue appears in React.js as well – Saurabh Sharma Aug 18 '17 at 10:53

0 Answers0