web-dev-qa-db-de.com

Winkel 2: Rückruf, wenn ngFor beendet ist

In Angular 1 habe ich eine benutzerdefinierte Anweisung ("repeater-ready") geschrieben, die zusammen mit ng-repeat zum Aufrufen einer Callback-Methode verwendet wird, wenn die Iteration abgeschlossen ist:

if ($scope.$last === true)
{
    $timeout(() =>
    {
        $scope.$parent.$parent.$eval(someCallbackMethod);
    });
}

Verwendung in Markup:

<li ng-repeat="item in vm.Items track by item.Identifier"
    repeater-ready="vm.CallThisWhenNgRepeatHasFinished()">

Wie kann ich mit ngFor in Angular 2 eine ähnliche Funktionalität erreichen?

15
Tobias Punke

Sie können so etwas verwenden ( ngFür lokale Variablen ):

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

Dann können Sie Eingabeneigenschaftsänderungen mit einem Setter abfangen

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

Sie können @ViewChildren für diesen Zweck verwenden

@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');
  }
}

ursprüngliche Antwort ist hierhttps://stackoverflow.com/a/37088348/5700401

17
Abhijit Jagtap

Für mich arbeitet in Angular2 mit TypeScript.

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

Dann können Sie mit dieser Funktion umgehen

public ngForCallback() {
  ...
}
8
FACode

Verwenden Sie anstelle von [ready] [attr.ready] wie unten

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

Ich habe in RC3 gefunden, dass die akzeptierte Antwort nicht funktioniert. Ich habe jedoch einen Weg gefunden, damit umzugehen. Für mich muss ich wissen, wann ngFor den MDL componentHandler zum Upgrade der Komponenten ausgeführt hat.

Zuerst benötigen Sie eine Direktive.

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();
    }
}

Importieren Sie diese anschließend in Ihre Komponente und fügen Sie sie den Anweisungen hinzu

import {UpgradeComponentsDirective} from './upgradeComponents.directive';

@Component({
    templateUrl: 'templates/mytemplate.html',
    directives: [UpgradeComponentsDirective]
})

Setzen Sie nun im HTML-Code das Attribut "Upgrade-Components" auf "true".

 <div *ngFor='let item of items;let last=last' [upgrade-components]="last ? true : false">

Wenn dieses Attribut auf true festgelegt ist, wird die Methode unter der @Input () - Deklaration ausgeführt. In meinem Fall wird componentHandler.upgradeAllRegistered () ausgeführt. Es kann jedoch für irgendetwas Ihrer Wahl verwendet werden. Durch die Bindung an die letzte Eigenschaft der ngFor-Anweisung wird diese ausgeführt, sobald sie abgeschlossen ist.

Sie müssen [attr.upgrade-components] nicht verwenden, auch wenn dies kein natives Attribut ist, da es jetzt eine unzulässige Direktive ist.

2

Ich schreibe eine Demo für diese Ausgabe. Die Theorie basiert auf der akzeptierten Antwort , aber diese Antwort ist nicht vollständig, da die li eine benutzerdefinierte Komponente sein sollte, die eine ready-Eingabe akzeptieren kann.

Ich schreibe eine vollständige Demo für diese Ausgabe.

Definieren Sie eine neue Komponente:

import {Component, Input, OnInit} aus '@ angle/core';

@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!');
    }
  }
}

vorlage

{{item}}

verwendung in der App-Komponente 

<app-li-ready *ngFor="let item of items;  let last1 = last;" [ready]="last1" [item]="item"></app-li-ready>

Sie sehen das Protokoll in der Konsole, druckt die gesamte Elementzeichenfolge und dann den isReady.

1
Xin Meng

Die Lösung ist ziemlich trivial. Wenn Sie wissen möchten, wann ngFor den Druck aller DOM-Elemente im Browserfenster abgeschlossen hat, gehen Sie wie folgt vor:

1. Fügen Sie einen Platzhalter hinzu

Fügen Sie einen Platzhalter für den Inhalt hinzu, der gedruckt werden soll:

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

2. Fügen Sie einen Container hinzu

Erstellen Sie einen Container mit display: none für den Inhalt. Wenn alle Elemente gedruckt sind, führen Sie display: block aus. contentPrinted ist eine Komponenten-Flag-Eigenschaft, die standardmäßig false lautet:

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

3. Erstellen Sie eine Rückrufmethode

Fügen Sie der Komponente onContentPrinted() hinzu, die sich nach dem Abschluss von ngFor deaktiviert:

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

Vergessen Sie nicht, ChangeDetectorRef zu verwenden, um ExpressionChangedAfterItHasBeenCheckedError zu vermeiden.

4. Verwenden Sie den Wert ngFor last

Deklarieren Sie last variable für ngFor. Verwenden Sie es in li, um eine Methode auszuführen, wenn dieses Element der letzte ist:

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

  • Verwenden Sie die Flag-Eigenschaft contentPrinted, um onContentPrinted()nur einmal auszuführen.
  • Verwenden Sie ng-container, um das Layout nicht zu beeinflussen.
1
vulp