ngForが完了した時に処理を走らせたい
ngFor
が完了した時に何らかの処理を走らせる必要が稀にあると思います
私の場合は、アプリ内のチャットで、チャットラインのスクロールバーを最下部に移動したいため必要でした。
(新規書き込みがチャットラインの下に追加されるslackやLineのスタイルのチャットです)
こういった場合にangularのライフサイクルのngInit
やngAfterViewInit
で処理を行うと、ngFor
の描画が完了されていないためスクロールバーが存在しておらず上手く行きません。
ngFor
でループさせる要素を@ViewChildren
で取得し、QueryList
のchagnes
を使うと完了後に処理を走らせることが出来ました
HTML側
-
ngFor
でループさせる要素に#でテンプレート参照を定義します
<app-chat-column #chatColumns
*ngFor="let chatData of (chatDataArray$ | async);trackBy:trackItem;"
[chatData]="chatData"></app-chat-column>
TypeScript側
-
@ViewChildren
でHTML側で定義したテンプレート参照からQueryList
を取得します - 取得した
QueryList
のchanges
でObservable
が扱えます。ngAfterViewInit
内でsubscribe
し、完了後の処理を実行させます
export class ChatLineComponent implements OnInit, AfterViewInit {
// ngForでループさせる要素のQueryList取得
@ViewChildren('chatColumns')
chatColumns: QueryList<any>;
// ~略~
ngAfterViewInit() {
this.chatColumns.changes
.subscribe(t => {
// 最下部にスクロール
this.chatLineScroll.nativeElement.scrollTop = this.chatLineScroll.nativeElement.scrollHeight;
});
}
これでngFor完了後の状態で処理を実行させられ、スクロールバーを最下部に持っていくことが出来ました。
初回のみなど条件がある場合は、subscribe
の前にpipe
で条件の絞り込みを行います。