问题
I am trying to create a carousel component for my Angular 2 application.
I want the carousel to be generic, so that it will support both these cases:
<myCarousel>
<div>first card</div>
<div>second card</div>
....
</myCarousel>
and the more generic
<myCarousel>
<myCard *ngFor="let card of cards" [card]="card"></myCard>
</myCarousel>
The problem is that the carousel component requires an initialisation to run after the *ngFor has completed, otherwise it won't be displayed correctly.
Since the data is coming from a web service call, I can't guess the exact timing, but I need the carousel component to observe, implicitly or explicitly, when *ngFor has completed. Can anybody help? Thank you!
回答1:
Fire event on last attempt of ngFor
as below
<myCard *ngFor="#card in cards; #last=last" [card]="card" [attr.ready]="last ? false : true"></myCard>
and in code do this
@Input()
set ready(isReady: boolean) {
if (isReady) someCallbackMethod();
}
Hope this helps :)
回答2:
You could use ContentChildren
.
@ContentChildren(MyCardComponent) cards: QueryList<MyCardComponent>;
ngOnAfterContentInit() {
this.cards
.changes
//.debounce(100) /* maybe add an additional debounce time.. */
.subscribe(cards => {
// received new cards..
});
}
回答3:
There is another Stackoverflow answer that already solves the problem: https://stackoverflow.com/a/36750875/463893
My solution is very similar: a directive (called CarouselItem) applied to the carousel elements inside the *ngFor, defining a boolean input that tells whether the element is the last, and a property (or eventemitter) that can be set to a function to call when the last element has been reached.
So the template becomes:
<myCarousel #carousel>
<myCard *ngFor="let card of cards; let l = last"
[card]="card"
CarouselItem
[ready]="l ? true : false"
[init]="carousel.initialize">
</myCard>
</myCarousel>
the variable #carousel is needed to be able to reference the carousel component from the myCard directive ( [init]="carousel.initialize" ).
The following is the code of the directive:
@Directive({
selector: `[CarouselItem]`
})
export class CarouselItem {
@Input('init') onInit: Function = () => {};
@Input() set ready(isReady: boolean) {
if (isReady)
setTimeout(()=>this.onInit(), 200);
};
}
And finally the carousel component contains a public initialization method.
public initialize= ()=> {
// perform initialisation
};
来源:https://stackoverflow.com/questions/40930435/angular-2-when-ngfor-completes-call-function-on-parent-component