J'ai une table qui a été générée avec * ngFor. Maintenant, à l'intérieur de cette table, j'ai 2 colonnes et 5 lignes. La première colonne contient une balise de sélection et la deuxième colonne affichera la valeur sélectionnée. Maintenant, le problème est que lorsque vous sélectionnez une valeur dans la balise select dans l'une des lignes, la valeur sélectionnée apparaît dans toutes les lignes.
Pour une meilleure compréhension du problème, veuillez vous référer à https://stackblitz.com/edit/angular-43oxrc
app.component.ts
<table>
<tbody>
<tr *ngFor="let item of [1,2,3,4,5]">
<td>
<select [(ngModel)]="selectedCategory">
<option *ngFor="let category of categoryCall(item)" [ngValue]="category">{{category}}</option>
</select>
</td>
<td>
Choosen Value: {{selectedCategory}}
</td>
</tr>
</tbody>
</table>
app.componenent.html
categoryCall(categoryName) {
if (categoryName == 1) {
this.categories = ["Value 1", "Value 2", "Value 3"];
}
else if (categoryName == 2) {
this.categories = ["Value 4", "Value 6", "Value 5", "Value 7"];
}
else if (categoryName == 3) {
this.categories = ["Value 7", "Value 8"];
}
return this.categories;
}
J'ai besoin de comme; Si vous choisissez une valeur dans la 1ère ligne, sa valeur ne doit apparaître que dans la 1ère ligne. Il ne doit apparaître dans aucune autre ligne
3 Réponses :
car le ngmodel selectedCategory est lié pour chaque sélection. Créez une liste de modèles que vous utilisez dans * ngFor.
J'ai mis à jour votre stackblitz stackblitz.com/edit/angular-xz4qft
Mais avec cette approche, nous obtenons une erreur comme "ExpressionChangedAfterItHasBeenCheckedError". Comment résoudre ça?
J'ai mis à jour le stackblitz. L'idée est de préparer votre liste avant de la consommer dans votre ngFor. Une autre idée est d'utiliser un tube pour obtenir la bonne liste de catégories. IMHO c'est une mauvaise idée d'utiliser les fonctions appelées directement à partir de HTML, car cette fonction appellera à chaque tick. Cela peut avoir un impact sur les performances, si la fonction a une complexité élevée. Pour éviter cela, vous devez définir le composant sur OnPush (recommandé par Angular Team).
Essayez de convertir selectedCategory en un tableau de chaînes et remplacez le ngModel par une fonction qui le remplit. Par exemple:
app.component.html
categories: any;
selectedCategory: any = [undefined, undefined, undefined, undefined, undefined];
categoryCall(categoryName) {
if (categoryName == 1) {
this.categories = ["Value 1", "Value 2", "Value 3"];
}
else if (categoryName == 2) {
this.categories = ["Value 4", "Value 6", "Value 5", "Value 7"];
}
else if (categoryName == 3) {
this.categories = ["Value 7", "Value 8"];
}
return this.categories;
}
changedCategory(value, item) {
this.selectedCategory[item-1] = value;
}
app.component.ts
<table>
<tbody>
<tr *ngFor="let item of [1,2,3,4,5]">
<td>
<select (change)="changedCategory($event.target.value, item)">
<option *ngFor="let category of categoryCall(item)" [ngValue]="category">{{category}}</option>
</select>
</td>
<td>
Choosen Value: {{selectedCategory[item-1]}}
</td>
</tr>
</tbody>
</table>
Vous ne pouvez pas le faire de cette façon. La raison est sélectionnéeCatégorie lie les cinq emplacements car il s'agit d'une valeur unique. Vous pouvez le faire comme ceci.
TS
<table>
<tbody>
<tr *ngFor="let item of items">
<td>
<select [(ngModel)]="item.selectedCategory">
<option *ngFor="let category of categoryCall(item.number)" [ngValue]="category">{{category}}</option>
</select>
</td>
<td>
Choosen Value: {{item.selectedCategory}}
</td>
</tr>
</tbody>
</table>
export class AppComponent {
selectedCategory: string;
categories: string[];
items = [];
constructor () {
this.addItems();
}
addItems() {
for (let i = 0; i < 5; i++) {
this.items.push({selectedCategory: null, number: i + 1});
}
}
}