web-dev-qa-db-ja.com

Angular 2:ngForが終了したときのコールバック

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で同様の機能を実現するにはどうすればよいですか?

22
Tobias Punke

次のようなものを使用できます( ngFor local variables ):

<li *ngFor="#item in Items; #last = last" [ready]="last ? false : true">

それから 入力プロパティの変更をインターセプターで設定

  @Input()
  set ready(isReady: boolean) {
    if (isReady) someCallbackMethod();
  }
15
Sasxa

そのために@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');
  }
}

元の回答はこちらhttps://stackoverflow.com/a/37088348/5700401

25
Abhijit Jagtap

私にとっては、TypeScriptを使用してAngular2で動作します。

<li *ngFor="let item in Items; let last = last">
  ...
  <span *ngIf="last">{{ngForCallback()}}</span>
</li>

次に、この関数を使用して処理できます

public ngForCallback() {
  ...
}
8
FACode

[準備完了]の代わりに、次のように[attr.ready]を使用します

 <li * ngFor = "#items in Items; #last = last" [attr.ready] = "last?false:true">
4

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]を使用する必要はありませんが、これはネイティブの属性ではありませんが、これは現在の真正なディレクティブであるためです。

3

解決策は非常に簡単です。 ngForがブラウザウィンドウへのすべてのDOM要素の印刷を完了するタイミングを知る必要がある場合は、次の手順を実行します。

1.プレースホルダーを追加する

印刷するコンテンツのプレースホルダーを追加します。

_<div *ngIf="!contentPrinted">Rendering content...</div>_

2.コンテナーを追加する

コンテンツ用に_display: none_を使用してコンテナーを作成します。すべてのアイテムが印刷されたら、_display: block_を実行します。 contentPrintedはコンポーネントフラグプロパティであり、デフォルトはfalseです。

_<ul [class.visible]="contentPrinted"> ...items </ul>_

3.コールバックメソッドを作成する

コンポーネントにonContentPrinted()を追加します。これにより、ngForの完了後に自身が無効になります。

onContentPrinted() { this.contentPrinted = true; this.changeDetector.detectChanges(); }

ChangeDetectorRefを避けるためにExpressionChangedAfterItHasBeenCheckedErrorを使用することを忘れないでください。

4. ngFor last値を使用します

lastngFor変数を宣言します。このアイテムが最後の1つの場合、li内で使用してメソッドを実行します。

<li *ngFor="let item of items; let last = last"> ... <ng-container *ngIf="last && !contentPrinted"> {{ onContentPrinted() }} </ng-container> <li>

  • contentPrintedコンポーネントフラグプロパティを使用して、onContentPrinted()一度だけを実行します。
  • _ng-container_を使用して、レイアウトに影響を与えません。
2
vulp

この問題のデモを作成します。理論は 受け入れられた答え に基づいていますが、liready入力を受け入れることができるカスタムコンポーネントである必要があるため、この答えは完全ではありません。

この問題について 完全なデモ と書きます。

新しいコンポーネントを定義します。

「@ 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が印刷されます。

1
Xin Meng