最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Slick Carousel with Angular 2 - Stack Overflow

programmeradmin2浏览0评论

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-selectorponent.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); 
    }
}

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); 
    }
}
Share Improve this question edited Mar 31, 2017 at 18:44 Stefan 14.9k17 gold badges91 silver badges152 bronze badges asked Oct 19, 2016 at 16:50 OvSleepOvSleep 2981 gold badge2 silver badges8 bronze badges 7
  • How are you populating your sources variable, is it via http call? – Stefan Svrkota Commented Oct 19, 2016 at 16:52
  • No, but I'm using a service mock, eventually it will. Now it's just calling that service and it's resolving a Promise (like in the firsts steps of the Tour Of Heroes Tutorial link) – OvSleep Commented Oct 19, 2016 at 16:56
  • 2 @OvSleep Could you pls share steps to work with slick in angular2 – Manu Commented Nov 21, 2016 at 11:39
  • 1 I don't understand how the import 'slick-slider' is resolved ? – Arnaud Commented Jan 5, 2017 at 7:08
  • I am new in angular2 Please can you help me with this issue:stackoverflow.com/questions/42925338/… – MedKostali Commented Mar 22, 2017 at 11:11
 |  Show 2 more comments

2 Answers 2

Reset to default 12

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>

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

发布评论

评论列表(0)

  1. 暂无评论