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
|
Show 2 more comments
2 Answers
Reset to default 12You 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...
sources
variable, is it viahttp
call? – Stefan Svrkota Commented Oct 19, 2016 at 16:52