Dans Angular 1, j'ai écrit une directive personnalisée ("repeater-ready") à utiliser avec ng-repeat
pour appeler une méthode de rappel une fois l'itération terminée:
if ($scope.$last === true)
{
$timeout(() =>
{
$scope.$parent.$parent.$eval(someCallbackMethod);
});
}
Utilisation dans le balisage:
<li ng-repeat="item in vm.Items track by item.Identifier"
repeater-ready="vm.CallThisWhenNgRepeatHasFinished()">
Comment puis-je obtenir une fonctionnalité similaire avec ngFor
in Angular 2?
Vous pouvez utiliser quelque chose comme ceci ( ngFor variables locales ):
<li *ngFor="#item in Items; #last = last" [ready]="last ? false : true">
Ensuite, vous pouvez Intercepter les modifications de propriétés d’entrée avec un setter
@Input()
set ready(isReady: boolean) {
if (isReady) someCallbackMethod();
}
Vous pouvez utiliser @ViewChildren à cette fin
@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');
}
}
Réponse d'origine icihttps://stackoverflow.com/a/37088348/5700401
Pour moi fonctionne dans Angular2 en utilisant TypeScript.
<li *ngFor="let item in Items; let last = last">
...
<span *ngIf="last">{{ngForCallback()}}</span>
</li>
Ensuite, vous pouvez vous servir de cette fonction
public ngForCallback() {
...
}
Au lieu de [prêt], utilisez [attr.ready] comme ci-dessous
<li * ngFor = "# item in Items; #last = last" [attr.ready] = "last? false: true">
J'ai trouvé dans RC3 la réponse acceptée ne fonctionne pas. Cependant, j'ai trouvé un moyen de régler ce problème. Pour moi, j'ai besoin de savoir quand ngFor a fini d'exécuter le gestionnaire de composants MDL pour mettre à niveau les composants.
D'abord, vous aurez besoin d'une directive.
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();
}
}
Importez ensuite ceci dans votre composant et ajoutez-le aux directives
import {UpgradeComponentsDirective} from './upgradeComponents.directive';
@Component({
templateUrl: 'templates/mytemplate.html',
directives: [UpgradeComponentsDirective]
})
Maintenant, dans le code HTML, définissez l'attribut "upgrade-components" sur true.
<div *ngFor='let item of items;let last=last' [upgrade-components]="last ? true : false">
Lorsque cet attribut est défini sur true, la méthode est exécutée sous la déclaration @Input (). Dans mon cas, il exécute composantHandler.upgradeAllRegistered (). Cependant, il pourrait être utilisé pour n'importe quoi de votre choix. En liant la propriété 'last' de l'instruction ngFor, celle-ci s'exécutera une fois terminée.
Vous n'aurez pas besoin d'utiliser [attr.upgrade-components] même s'il ne s'agit pas d'un attribut natif car il s'agit maintenant d'une directive de bonne foi.
J'écris une démo pour ce numéro. La théorie est basée sur la réponse acceptée mais cette réponse n'est pas complète, car li
doit être un composant personnalisé pouvant accepter une entrée ready
.
J'écris une démo complète pour ce numéro.
Définir un nouveau composant:
import {Component, Input, OnInit} à partir de '@ angular/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!');
}
}
}
modèle
{{item}}
utilisation dans le composant d'application
<app-li-ready *ngFor="let item of items; let last1 = last;" [ready]="last1" [item]="item"></app-li-ready>
Vous verrez que le journal dans la console imprimera toute la chaîne d’éléments, puis l’isReady.
La solution est assez triviale. Si vous avez besoin de savoir quand ngFor
termine d'imprimer tous les éléments DOM dans la fenêtre du navigateur, procédez comme suit:
Ajoutez un espace réservé pour le contenu en cours d'impression:
<div *ngIf="!contentPrinted">Rendering content...</div>
Créez un conteneur avec display: none
pour le contenu. Lorsque tous les éléments sont imprimés, faites display: block
. contentPrinted
est une propriété d'indicateur de composant, dont la valeur par défaut est false
:
<ul [class.visible]="contentPrinted">
...items
</ul>
Ajoutez onContentPrinted()
au composant, qui se désactive après la fin de ngFor
:
onContentPrinted() {
this.contentPrinted = true;
this.changeDetector.detectChanges();
}
Et n'oubliez pas d'utiliser ChangeDetectorRef
pour éviter ExpressionChangedAfterItHasBeenCheckedError
.
last
valueDéclarez la variable last
sur ngFor
. Utilisez-le dans li
pour exécuter une méthode lorsque cet élément est le dernier dernier :
<li *ngFor="let item of items; let last = last">
...
<ng-container *ngIf="last && !contentPrinted">
{{ onContentPrinted() }}
</ng-container>
<li>
contentPrinted
pour exécuter onContentPrinted()
une seule fois .ng-container
pour ne pas affecter la mise en page.