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で条件の絞り込みを行います。