web-dev-qa-db-fra.com

Angular 2: rappel lorsque ngFor est terminé

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?

15
Tobias Punke

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

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

17
Abhijit Jagtap

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() {
  ...
}
8
FACode

Au lieu de [prêt], utilisez [attr.ready] comme ci-dessous

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

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.

2
Warren Schilpzand

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.

1
Xin Meng

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:

1. Ajouter un espace réservé

Ajoutez un espace réservé pour le contenu en cours d'impression:

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

2. Ajouter un conteneur

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> 

3. Créer une méthode de rappel

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.

4. Utilisez ngFor last value

Dé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>

  • Utilisez la propriété de drapeau de composant contentPrinted pour exécuter onContentPrinted() une seule fois .
  • Utilisez ng-container pour ne pas affecter la mise en page.
1
vulp