comment utiliser la piste à l'intérieur de ngFor angular 2
a essayé toutes les syntaxes que je peux deviner ne pouvait pas faire ça fonctionne !
<!--- 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 méthode qui a fonctionné pour moi a été
-
méthode de Création de Classe controller
identifier (index, post: Post){ retour de courrier.id }
et
<ion-card *ngFor="#post of posts;trackBy:identify">
</ion-card>
est-ce le seul moyen ? est-ce que je ne peux pas juste spécifier la ligne de propriété pour trackBy ?
4 réponses
comme indiqué dans le commentaire @Eric, et après beaucoup de lecture et de jeu, voici comment utiliser trackBy en angular2
- la première chose que vous devez savoir sa syntaxe pas la même que angular1, maintenant vous devez le séparer de la boucle for avec un
;
.
Utilisation 1: Piste d'une 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 à
- créer un poste variable local;
- vous dites à trackBy d'attendre jusqu'à ce que cette variable locale soit prête "vous faites cela en utilisant l'opérateur elvis 'le point d'interrogation après le variable name', puis utiliser son id comme tracker.
donc
// 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 en tant angulaire du 1
ng-repeat="post in posts track by post.id"
Utilisation 2: Piste à l'aide de 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 fournissant 2 paramètres: l'index de la boucle et l'élément courant.
pour obtenir la même chose avec L'Angle 1, je faisais:
<li ng-repeat="post in posts track by identify($index,post)"></li>
app.controller(function($scope){
$scope.identify = function(index, item) {return item.id};
});
comme vous l'avez déjà reconnu, l'utilisation d'une fonction est la seule façon d'utiliser trackBy
en angle 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 fausses. En commençant par L'Angular 2.4.1 ceci lancera également une erreur dans l'application.
Le concept derrière trackBy:
-
ngFor
of angular optimise automatiquement l'affichage des objets modifiés/créés/supprimés en traçant l'identité de l'objet. Ainsi, si vous créez tous les nouveaux objets dans la liste et que vous utilisez ensuitengFor
, cela rendra la liste entière. -
considérons un scénario où malgré toutes les optimisations
ngFor
, le rendu prend encore du temps. Dans dans ce cas, on utilisetrackBy
. 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.
l'exécution d'Un exemple:
<!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/zone.js@0.6.21/dist/zone.js"></script>
<script src="https://unpkg.com/reflect-metadata@0.1.9/Reflect.js"></script>
<script src="https://unpkg.com/systemjs@0.19.41/dist/system.js"></script>
<script src="https://unpkg.com/typescript@2.1.4/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>
Cette solution simple a fonctionné pour mon scénario
<ion-card *ngFor="let post of posts;let i = index">
{{i+1}}
</ion-card>
EDIT: Comme suggéré par Jeremy Thille ci-dessous, vous devez utiliser let
au lieu de #
, #
est déconseillée dans les dernières versions de Angular2.