Angular 1で、反復が完了したときにコールバックメソッドを呼び出すためにng-repeat
で使用するカスタムディレクティブ( "repeater-ready")を記述しました。
if ($scope.$last === true)
{
$timeout(() =>
{
$scope.$parent.$parent.$eval(someCallbackMethod);
});
}
マークアップでの使用:
<li ng-repeat="item in vm.Items track by item.Identifier"
repeater-ready="vm.CallThisWhenNgRepeatHasFinished()">
ngFor
in Angular 2で同様の機能を実現するにはどうすればよいですか?
次のようなものを使用できます( ngFor local variables ):
<li *ngFor="#item in Items; #last = last" [ready]="last ? false : true">
@Input()
set ready(isReady: boolean) {
if (isReady) someCallbackMethod();
}
そのために@ViewChildrenを使用できます
@Component({
selector: 'my-app',
template: `
<ul *ngIf="!isHidden">
<li #allTheseThings *ngFor="let i of items; let last = last">{{i}}</li>
</ul>
<br>
<button (click)="items.Push('another')">Add Another</button>
<button (click)="isHidden = !isHidden">{{isHidden ? 'Show' : 'Hide'}}</button>
`,
})
export class App {
items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
@ViewChildren('allTheseThings') things: QueryList<any>;
ngAfterViewInit() {
this.things.changes.subscribe(t => {
this.ngForRendred();
})
}
ngForRendred() {
console.log('NgFor is Rendered');
}
}
私にとっては、TypeScriptを使用してAngular2で動作します。
<li *ngFor="let item in Items; let last = last">
...
<span *ngIf="last">{{ngForCallback()}}</span>
</li>
次に、この関数を使用して処理できます
public ngForCallback() {
...
}
[準備完了]の代わりに、次のように[attr.ready]を使用します
<li * ngFor = "#items in Items; #last = last" [attr.ready] = "last?false:true">
RC3で、受け入れられた答えが機能しないことがわかりました。しかし、私はこれに対処する方法を見つけました。私にとっては、ngForがMDL componentHandlerの実行を完了してコンポーネントをアップグレードしたことを知る必要があります。
まず、ディレクティブが必要になります。
upgradeComponents.directive.ts
import { Directive, ElementRef, Input } from '@angular/core';
declare var componentHandler : any;
@Directive({ selector: '[upgrade-components]' })
export class UpgradeComponentsDirective{
@Input('upgrade-components')
set upgradeComponents(upgrade : boolean){
if(upgrade) componentHandler.upgradeAllRegistered();
}
}
次に、これをコンポーネントにインポートし、ディレクティブに追加します
import {UpgradeComponentsDirective} from './upgradeComponents.directive';
@Component({
templateUrl: 'templates/mytemplate.html',
directives: [UpgradeComponentsDirective]
})
HTMLで、「upgrade-components」属性をtrueに設定します。
<div *ngFor='let item of items;let last=last' [upgrade-components]="last ? true : false">
この属性をtrueに設定すると、@ Input()宣言の下でメソッドが実行されます。私の場合、componentHandler.upgradeAllRegistered()を実行します。ただし、任意の選択に使用できます。 ngForステートメントの 'last'プロパティにバインドすることにより、終了時に実行されます。
[attr.upgrade-components]を使用する必要はありませんが、これはネイティブの属性ではありませんが、これは現在の真正なディレクティブであるためです。
解決策は非常に簡単です。 ngFor
がブラウザウィンドウへのすべてのDOM要素の印刷を完了するタイミングを知る必要がある場合は、次の手順を実行します。
印刷するコンテンツのプレースホルダーを追加します。
_<div *ngIf="!contentPrinted">Rendering content...</div>
_
コンテンツ用に_display: none
_を使用してコンテナーを作成します。すべてのアイテムが印刷されたら、_display: block
_を実行します。 contentPrinted
はコンポーネントフラグプロパティであり、デフォルトはfalse
です。
_<ul [class.visible]="contentPrinted"> ...items </ul>
_
コンポーネントにonContentPrinted()
を追加します。これにより、ngFor
の完了後に自身が無効になります。
onContentPrinted() { this.contentPrinted = true; this.changeDetector.detectChanges(); }
ChangeDetectorRef
を避けるためにExpressionChangedAfterItHasBeenCheckedError
を使用することを忘れないでください。
last
値を使用しますlast
でngFor
変数を宣言します。このアイテムが最後の1つの場合、li
内で使用してメソッドを実行します。
<li *ngFor="let item of items; let last = last"> ... <ng-container *ngIf="last && !contentPrinted"> {{ onContentPrinted() }} </ng-container> <li>
contentPrinted
コンポーネントフラグプロパティを使用して、onContentPrinted()
一度だけを実行します。ng-container
_を使用して、レイアウトに影響を与えません。この問題のデモを作成します。理論は 受け入れられた答え に基づいていますが、li
はready
入力を受け入れることができるカスタムコンポーネントである必要があるため、この答えは完全ではありません。
この問題について 完全なデモ と書きます。
新しいコンポーネントを定義します。
「@ angular/core」から{Component、Input、OnInit}をインポートします。
@Component({
selector: 'app-li-ready',
templateUrl: './li-ready.component.html',
styleUrls: ['./li-ready.component.css']
})
export class LiReadyComponent implements OnInit {
items: string[] = [];
@Input() item;
constructor() { }
ngOnInit(): void {
console.log('LiReadyComponent');
}
@Input()
set ready(isReady: boolean) {
if (isReady) {
console.log('===isReady!');
}
}
}
テンプレート
{{item}}
アプリコンポーネントでの使用
<app-li-ready *ngFor="let item of items; let last1 = last;" [ready]="last1" [item]="item"></app-li-ready>
コンソールにログが表示され、すべてのアイテム文字列が印刷されてからisReadyが印刷されます。