web-dev-qa-db-fra.com

comment utiliser track par inside ngFor angular 2

j'ai essayé toutes les syntaxes que je peux deviner, ça ne fonctionnera pas!

<!--- THIS WORKS FINE --->
<ion-card *ngFor="#post of posts">
{{post|json}}
</ion-card>

<!--- BLANK PAGE --->
<ion-card *ngFor="#post of posts track by post.id">
{{post|json}}
</ion-card>

<!--- Exception : Cannot read property 'id' of undefined --->
<ion-card *ngFor="#post of posts;trackBy:post.id">
{{post|json}}
</ion-card>

<!--- Exception : Cannot read property 'undefined' of undefined --->
<ion-card *ngFor="#post of posts;trackBy:posts[index].id">
{{post|json}}
</ion-card>

<!--- Blank page no exception raised !  --->
<ion-card *ngFor="#post of posts;#index index;trackBy:posts[index].id">
{{post|json}}
</ion-card>

la seule approche qui a fonctionné pour moi était

  1. Création d'une méthode dans la classe de contrôleur

    identifier (index, post: Post) {return post.id}

et

<ion-card *ngFor="#post of posts;trackBy:identify">
</ion-card>

est-ce seulement un moyen? ne puis-je pas simplement spécifier un nom de propriété inline pour trackBy?

44
Zalaboza

Comme indiqué dans le commentaire @Eric, et après de nombreuses lectures et jeux, voici comment utiliser trackBy dans angular2

  1. la première chose dont vous avez besoin pour connaître sa syntaxe différente de celle angular1, maintenant vous devez la séparer de la boucle for avec un ;.

sage 1: Suivi par propriété de l'objet

 // starting v2. 1 this will throw error, you can only use functions in trackBy from now on

<ion-card *ngFor="let post of posts;trackBy:post?.id">
</ion-card> // **DEPRECATED**
---or---
<ion-card *ngFor="let post of posts;trackBy:trackByFn">
</ion-card>

ici vous demandez à angular2 de

  1. créer une variable locale post;
  2. vous dites à trackBy d'attendre jusqu'à ce que cette variable locale soit prête "vous le faites en utilisant l'opérateur elvis 'le point d'interrogation après le nom de la variable', puis utilisez son identifiant comme suivi.

alors

// starting v2. 1 this will throw error, you can only use functions in trackBy from now on

*ngFor="#post of posts;trackBy:post?.id"

est ce que même que angular 1

ng-repeat="post in posts track by post.id"

sage 2: Suivre en utilisant votre propre fonction

@Page({
    template: `
        <ul>
            <li *ngFor="#post of posts;trackBy:identify">
              {{post.data}}
            </li>
        </ul>
    `
})
export class HomeworkAddStudentsPage {
    posts:Array<{id:number,data:string}>;   

    constructor() {
        this.posts = [  {id:1,data:'post with id 1'},
                        {id:2,data:'post with id 2'} ];
    }

    identify(index,item){
      //do what ever logic you need to come up with the unique identifier of your item in loop, I will just return the object id.
      return post.id 
     }

}

trackBy peut prendre un nom de callback, et il l'appellera pour nous en fournissant 2 paramètres: l'index de la boucle et l'élément en cours.

Pour obtenir le même résultat avec Angular 1, je faisais autrefois:

<li ng-repeat="post in posts track by identify($index,post)"></li>

app.controller(function($scope){
  $scope.identify = function(index, item) {return item.id};
});
82
Zalaboza

Comme vous l'avez déjà reconnu, l'utilisation d'une fonction est le seul moyen d'utiliser trackBy dans Angular 2

<ion-card *ngFor="#post of posts;trackBy:identify"></ion-card>

La documentation officielle indique que https://angular.io/docs/ts/latest/api/common/index/NgFor-directive.html

Toutes les autres informations sur <ion-card *ngFor="let post of posts;trackBy:post?.id"></ion-card> sont erronées. Commençant par Angular 2.4.1, cela provoquera également une erreur dans l'application.

9
Volker Andres

Le concept derrière trackBy:

  1. ngFor sur angular optimise automatiquement l'affichage des objets modifiés/créés/supprimés en suivant leur identité. Ainsi, si vous créez tous les nouveaux objets de la liste, puis utilisez ngFor, la liste entière sera rendue.

  2. Prenons un scénario où malgré toutes les optimisations ngFor, le rendu prend encore du temps. Dans ce cas, nous utilisons trackBy. Ainsi, nous pouvons fournir un autre paramètre pour suivre les objets que l'identité de l'objet qui est un critère de suivi par défaut.

Un exemple en cours d'exécution:

<!DOCTYPE html>
<html>

<head>
    <title>Angular 2.1.2 + TypeScript Starter Kit</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <script src="https://unpkg.com/[email protected]/dist/zone.js"></script>
    <script src="https://unpkg.com/[email protected]/Reflect.js"></script>
    <script src="https://unpkg.com/[email protected]/dist/system.js"></script>
    <script src="https://unpkg.com/[email protected]/lib/TypeScript.js"></script>
    <script src="config.js"></script>
  <script>
      System.import('app')
          .catch(console.error.bind(console));
    </script>
</head>

<body>
    <my-app>
        loading...
    </my-app>
</body>

</html>
2
Ruchi Wadhwa