2017-10-10 7 views
2

Ich versuche ein dynamisches Formular für Benutzer in der Bauindustrie zu erstellen, die Eingaben für ein Gebäude (jeder Anzahl von Stockwerken) auf einer Etage als Basis analysieren wird so:Angular * ngFor mit ngModel mit Select hat eine unerwartete Bindung

  1. Benutzer zunächst mit einem Formular für eine einstöckige Form, aber angesichts der Möglichkeit, fügen eine zusätzliche geschossigen vorgestellt:

  2. Wir sollten in der Lage sein, hinzufügen eine beliebige Anzahl von zusätzlichen Stockwerken, und löschen Sie ein bestimmtes Stockwerk, falls gewünscht.

Methode

Um dies zu erreichen, ich versuche * ngFor zu nutzen und ein Array iterieren, die in den Daten nehmen, ngModel in dem Array zu jedem Objekt zu binden, verwenden.

component.html

<form *ngFor = "let storey of storeyData; let i = index; trackBy: trackByFn(i)"> 
    <md-select placeholder="Floor type" name ="floorTypeSelector{{i}}" [(ngModel)]="storeyData[i].floorTypes[0]"> 
     <md-option *ngFor="let floorType of floorTypes" [value]="floorType.value"> 
      {{floorType.viewValue}} 
     </md-option> 
    </md-select> 

<button md-raised-button (click)="incrementStoreyNumber()"> 
    <md-icon>library_add</md-icon> 
    Add storey 
</button> 

component.ts

export class FloorDetailsFormComponent implements OnInit { 

selectedFloorType = []; 
floorTypes = [ 
{value: 'concreteSlab', viewValue: 'Concrete slab'}, 
{value: 'suspendedTimber', viewValue: 'Suspended timber'}, 
{value: 'suspendedSlab', viewValue: 'Suspended slab'}, 
{value: 'wafflePod', viewValue: 'Waffle pod'} 
]; 

storeyData = [{floorTypes: [],floorAreas:[] }]; 
storeyDataTemplate = {floorTypes: [], floorAreas:[]}; 

incrementStoreyNumber(){ 
    this.storeyData.push(this.storeyDataTemplate); 
} 

trackByFn(index){ 
return index; 
} 
constructor() { } 
ngOnInit() { 
} 

Problem

Es scheint, dass die ersten beiden Stockwerken, um ihre Variablen binden korrekt, aber die ausgewählten Werte des Änderns jeder der zweiten bis n-ten Stockwerke ändert die anderen Stockwerke (außer dem ersten).

Nach der Suche nach anderen Posts über ähnliche Probleme, bin ich immer noch ratlos, warum das passiert. Ein Problem, das andere hatten, war, dass der Name des Elements nicht für jede Iteration der * ngFor-Schleife unterschieden wurde. Wenn ich jedoch mein console.log ansehe, kann ich den Namen jedes Elements sehen, das indiziert wird. Ein interessantes Ding, das ich gesehen habe, ist, dass, wenn ich das storeData-Array auf eine Länge von n Stockwerken in der Typoskript-Datei erweitere, alle Stockwerke bis n an ihre eigene unabhängige Variable binden, wie sie sollten, und alle Stockwerke n +1, die später hinzugefügt werden, haben das gleiche Problem.

Ich habe versucht, mit der TrackBy-Funktion, aber ich kann nicht scheinen, um dies auch zu arbeiten. Ich habe wirklich kein Verständnis dafür, was unter der Haube passiert, wenn ich versuche, die * ngFor-Reihe im laufenden Betrieb zu erweitern. Vielleicht ist das nur eine schlechte Übung? Wenn Sie mir helfen könnte hier draußen würde ich sehr dankbar sein (auch wenn seine „hey, auf diese lesen up“)

+0

Schauen Sie sich meine Antwort hier, ich denke, diese Lösung für Ihr Problem ist: https://stackoverflow.com/questions/41265761/using-ngfor-with-ngmodel-dynamic-data-wrong-behaviour –

+0

Vielen Dank für die Antwort Stefan.Die Hintergrundinformationen zur Formgruppe waren interessant. Ich wechselte zu [ngModelOptions] = "{standalone: ​​true}" und entfernte das Namensattribut, wie es in Ihrer verknüpften Lösung vorgeschlagen wurde, weist jedoch immer noch das gleiche Verhalten auf. Dies ist eine der vorgeschlagenen Lösungen, die ich zuvor ohne viel Erfolg ausprobiert habe. – LNKX

+0

Implementieren Sie trackby auf der zweiten ngfor auch. Und ändern Sie es für eine argumentlose Version: trackBy: trackByFn und trackByFn (Artikel, Index) {Return-Index} – Vega

Antwort

0

Das Problem ist in dieser Zeile:

this.storeyData.push(this.storeyDataTemplate); 

Wenn Sie hinzufügen storeyDataTemplate Bei storeData ist es das gleiche Objekt, das bei jedem Drücken gebunden wird, und ngFür die Verfolgung desselben Objekts. Wenn Sie ändern:

this.storeyData.push({floorTypes: [], floorAreas:[]}); 

wird es funktionieren.

DEMO

+1

Das war's! Du bist ein Genie :) Vielen Dank für die Zeit, die du gebraucht hast, um das Problem zu verstehen. Dieser Fix erklärt all das Verhalten, das ich gesehen habe, und gibt mir einige zusätzliche Einblicke in die Funktionsweise von ngFor. Sobald ich genug Reputation habe (ich bin erst am 8. ...) werde ich das mit Begeisterung auffrischen :) – LNKX

Verwandte Themen