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?
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();
}
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
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() {
...
}
Verwenden Sie anstelle von [ready] [attr.ready] wie unten
<li * ngFor = "# item in Items; #last = last" [attr.ready] = "last? false: true">
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.
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.
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:
Fügen Sie einen Platzhalter für den Inhalt hinzu, der gedruckt werden soll:
<div *ngIf="!contentPrinted">Rendering content...</div>
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>
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.
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>
contentPrinted
, um onContentPrinted()
nur einmal auszuführen.ng-container
, um das Layout nicht zu beeinflussen.