web-dev-qa-db-fra.com

ng2: Comment créer une variable dans la boucle ngFor

J'essaie de savoir comment créer une variable dans une boucle ngFor.

J'ai une boucle comme celle-ci:

<td *ngFor="#prod of products">
  <a href="{{getBuild(branch,prod)?.url}}">
    {{getBuild(branch,prod)?.status}}
   </a>
</td>

Vous pouvez voir que l'appel "getBuild" doit être répété plusieurs fois. (beaucoup plus de fois dans mon exemple actuel). Je voudrais un moyen de créer cette variable dans le modèle une fois dans la boucle et de le réutiliser simplement. Y a-t-il un moyen de faire cela?

27
Allen

Je pense que les variables locales (définies avec le caractère #) ne s'appliquent pas à votre cas d'utilisation.

En fait, lorsque vous définissez une variable locale sur un élément HTML, elle correspond au composant, le cas échéant. Lorsqu'il n'y a pas de composant sur l'élément, la variable fait référence à l'élément lui-même.

La spécification d'une valeur pour une variable locale vous permet de sélectionner une directive spécifique associée à l'élément actuel. Par exemple:

<input #name="ngForm" ngControl="name" [(ngModel)]="company.name"/>

définira l'instance de la directive ngForm associée au courant dans la variable name.

Les variables locales ne ciblent donc pas ce que vous voulez, c’est-à-dire la définition d’une valeur créée pour l’élément actuel d’une boucle.

Si vous essayez de faire quelque chose comme ça:

<div *ngFor="#elt of eltList" >
  <span #localVariable="elt.title"></span>
  {{localVariable}}
</div>

Vous aurez cette erreur suivante:

Error: Template parse errors:
There is no directive with "exportAs" set to "elt.title" ("
  <div *ngFor="#elt of eltList" >
    <span [ERROR ->]#localVariable="elt.title"></span>
    {{localVariable}}
  </div>
"): AppComponent@2:10

Angular2 cherche en fait une directive correspondant au nom fourni elt.title ici) ... Voir ce dossier pour reproduire l'erreur: https://plnkr.co/edit/qcMGr9FS7yQD8LbX18uY?p=preview

Voir ce lien: http://victorsavkin.com/post/119943127151/angular-2-template-syntax , section "Variables locales" pour plus de détails.

En plus de l'élément actuel de l'itération, ngFor fournit uniquement un ensemble de valeurs exportées pouvant être associées à des variables locales: index, last, even et odd.

Voir ce lien: https://angular.io/docs/ts/latest/api/common/NgFor-directive.html

Ce que vous pouvez faire est de créer un sous-composant pour afficher les éléments dans la boucle. Il acceptera l'élément actuel en tant que paramètre et créera votre "variable locale" en tant qu'attribut du composant. Vous pourrez ensuite utiliser cet attribut dans le modèle du composant afin qu'il soit créé une fois par élément dans la boucle. Voici un échantillon:

@Component({
  selector: 'elt',
  template: `
    <div>{{attr}}</div>
  `
})
export class ElementComponent {
  @Input() element;

  constructor() {
    // Your old "localVariable"
    this.attr = createAttribute(element.title);
  }

  createAttribute(_title:string) {
    // Do some processing
    return somethingFromTitle;
  }
}

et la façon de l'utiliser:

<div *ngFor="#elt of eltList" >
  <elt [element]="elt></elt>
</div>
12
Thierry Templier

Je pense qu’il s’agit d’un cas classique de fabrication d’un sous-composant.

<td *ngFor="#prod of products">
    <subComp [prod]=prod></subComp>
</td>

Votre composant aurait alors une entrée prod et exécuterait la fonction requise une fois dans OnInit.

Exemple simple plunk here

13
Mark Meyer

Non, mettez en cache le résultat dans getBuild pour chaque combinaison branch/prod ou tant qu'elle est appelée avec les mêmes valeurs que précédemment. 

2
Günter Zöchbauer

Avec angular 4, vous pouvez faire ceci:

<td *ngFor="#prod of products">
  <div *ngIf="getBuild(branch,prod); let build">
    <a href="{{build.url}}">
     {{build.status}}
    </a>
  </div>
</td>
1
davidivad