Slick Carousel with Angular 2

删除回忆录丶 提交于 2019-11-27 12:55:50

问题


Hi I'm starting with Angular 2 and trying to make this carousel plugin to work: slick

After a while I managed to make it work like a Component like this:

import { Component, Input, ElementRef, AfterViewInit, AfterContentInit} from '@angular/core';
declare var jQuery: any;

@Component({
    selector: 'slick-slider',
    template: `
        <ng-content></ng-content>
    `
})
export class SlickSliderComponent implements AfterContentInit{
    @Input() options: any;

    $element: any;

    defaultOptions: any = {};

    constructor(private el: ElementRef) {
    }

    ngAfterContentInit() {
        for (var key in this.options) {
            this.defaultOptions[key] = this.options[key];
        }

        this.$element = jQuery(this.el.nativeElement).slick(this.defaultOptions);
    }
}

And I would use it like this on a template:

<slick-slider>
    <div><img class="btn btn-lg" src="/assets/img/img1.png" /></div>
    <div><img class="btn btn-lg" src="/assets/img/img2.png" /></div>
    <div><img class="btn btn-lg" src="/assets/img/img3.png" /></div>
    <div><img class="btn btn-lg" src="/assets/img/img4.png" /></div>
    <div><img class="btn btn-lg" src="/assets/img/img5.png" /></div>
</slick-slider>

This works fine. But when I try to use it inside *ngFor like this:

<slick-slider>
    <div *ngFor="let source of sources">
        <img class="btn btn-lg" (click)="watchSource(source)" src="/assets/img/{{source.name}}.png" />
    </div>
</slick-slider>

It stops working. I assume is because the init of the slider is done before the <div> elements are being rendered. Because I end up with this rendered html:

<slick-slider class="slick-initialized slick-slider">
    <div>
      <img ... >
    </div>
    <div>
      <img ... >
    </div>
    <div>
      <img ... >
    </div>
    <div>
      <img ... >
    </div>

    <div aria-live="polite" class="slick-list draggable">
      <div class="slick-track" role="listbox" style="opacity: 1; width: 0px; transform: translate3d(0px, 0px, 0px);">
        <!-- Divs should be rendered here with slick styles included -->
      </div>
  </div>
</slick-slider>

Any idea how to make this work? I tried using "ngAfterContentInit" and "ngAfterViewInit" neither seem to work.

This is the component using the SlickSliderComponent:

import { Component, OnInit } from '@angular/core'
import { DeviceSource } from './device-source'
import { RemoteService } from './remote.service';

@Component({
    selector: 'device-selector',
    moduleId: module.id,
    templateUrl: 'device-selector.component.html',
    providers: []
})



export class DeviceSelectorComponent implements OnInit {

    sources: [DeviceSource];

    ngOnInit(): void {
        this.getDeviceSources();
    }

    constructor(private remoteService: RemoteService){}

    getDeviceSources(): void {
        this.remoteService.getDeviceSources().then(sources => this.sources = sources);
    }
}

And here is the service used:

import { Injectable } from '@angular/core'
import { DeviceSource } from './device-source'

export const DEVICE_SOURCES:[DeviceSource]=
[
    {id: 1, dispayName: 'TV', name:'tv'},
    {id: 2, dispayName: 'Chrome', name:'chrome'},
    {id: 3, dispayName: 'Cable', name:'cable'},
    {id: 4, dispayName: 'XBox', name:'xbox'},
    {id: 4, dispayName: 'Pi', name:'pi'},

];


@Injectable()
export class RemoteService {
    getDeviceSources(): Promise<[DeviceSource]> {
        return Promise.resolve(DEVICE_SOURCES); 
    }
}

回答1:


You should add *ngIf directive to your slick-slider so it is inserted into DOM after data source is populated, in this case it is variable sources:

<slick-slider *ngIf="sources">
    <div *ngFor="let source of sources">
        <img class="btn btn-lg" (click)="watchSource(source)" src="/assets/img/{{source.name}}.png" />
    </div>
</slick-slider>



回答2:


In my case the trick with *ngIf was not enough. Im calling REST service in ngOnInit and receiving response where in subscription I'm defining the array. The only possible workaround for me was to add slick items manually by slick function 'slickAdd' directly from typescript.

jQuery('.my-slick').slick('slickAdd', '<div><h3>ahoj</h3></div>');

Maybe it will help somebody...



来源:https://stackoverflow.com/questions/40137285/slick-carousel-with-angular-2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!