Reputation: 6685
There is a component:
<my-component></my-component>
it's component receives a stream of numbers as @Input
<my-component [data]="numbers$ | async"></my-component>
inside the component we update the model:
@Component({...})
class MyComponent {
numbers: number[] = [];
@Input
set data(numbers: number[]) {
this.numbers = numbers;
}
constructor() {}
myCallback() { }
}
then render the list of numbers, like this:
<ul>
<li *ngFor="number of numbers">{{number}}</li>
</ul>
How to detect that *ngFor
has rendered all elements? And how to invoke callback function myCallback
after elements have been appended to the DOM?
Upvotes: 5
Views: 7835
Reputation: 24464
You can create a directive to detect the elemntmrender to the dom and run a method at that time
import { Directive , Output ,EventEmitter } from '@angular/core';
@Directive({
selector: '[rendered]'
})
export class RenderedDirective {
@Output() rendered:EventEmitter<any> = new EventEmitter();
ngAfterViewInit() {
this.rendered.emit()
}
}
ngAfterViewInit will called after Angular has fully initialized a and render li elemnt
MyComponent
export class MyComponentComponent {
numbers: number[] = [];
@Input() set data(numbers: number[]) {
this.numbers = numbers;
}
myCallback(elm) {
console.log(elm)
}
}
template
<ul>
<li #li *ngFor="let n of numbers" (rendered)="myCallback(li)">
{{n}}
</li>
</ul>
Upvotes: 2
Reputation: 24464
You can use ViewChildren
to get the QueryList of elements or directives from the view DOM. Any time a child element is added, removed, or moved, the query list will be updated, and the changes observable of the query list will emit a new value.
import { Component, OnInit, Input, ViewChildren, QueryList } from '@angular/core';
@Component({
selector: 'my-component',
templateUrl: './my-component.component.html',
styleUrls: ['./my-component.component.css']
})
export class MyComponentComponent {
numbers: number[] = [];
@ViewChildren('li') elements: QueryList<any>;
@Input() set data(numbers: number[]) {
this.numbers = numbers;
}
ngAfterViewInit() {
this.elements.changes.subscribe(li => {
li.forEach(elm => this.myCallback(elm.nativeElement))
})
}
myCallback(elm) {
console.log(elm)
}
}
template
<ul>
<li #li *ngFor="let n of numbers">
{{n}}
</li>
</ul>
myCallback will log each elemnt but you still has access to all li elemnts
Upvotes: 7
Reputation: 2877
this happens in NgInit
https://angular.io/guide/lifecycle-hooks
ngOnInit()
Initialize the directive/component after Angular first displays the data-bound properties and sets the directive/component's input properties.Called once, after the first ngOnChanges().
Update:
I have propably misunderstood your question. You dont have any update on the ngFor. What is your usecase? Maybe there are different solutions for this.
Upvotes: 1