Angular model and synchronization output

I have an Angular component that has a button that adds a new object to an array that serves as a model. In my component template, I have a * ngFor loop that iterates through the objects in the array and displays the input fields for the properties of the object. I also have a delete button next to each object that removes the object from the array. When I do the following steps, the user interface does not synchronize with the model and empties the fields of all elements except the first.

  • Add 3 new objects to the array by clicking the "Add" button
  • Fill in the input fields with some data
  • Click the "Delete" button on the middle item to remove it.
  • Add 1 new object by clicking the "Add" button

What makes the user interface out of sync with the model?

Here is a Plunker example that demonstrates the problem Example I also added a line in the template that shows what is in the model array.

@Component({ selector: 'my-app', template: ` <div> <button (click)="things.push({})">+ Add new thing</button> <br /> <br /> <form #contactForm="ngForm"> <ng-container *ngFor="let thing of things;let i = index"> <input [(ngModel)]="thing.name" name="name-{{i}}" id="name-{{i}}" placeholder="name"/> <br /> <input [(ngModel)]="thing.otherstuff" name="other-{{i}}" id="other-{{i}}" placeholder="other" /> <button (click)="things.splice(i, 1)">Remove</button> <br /> <br /> </ng-container> </form> {{things | json}} </div> `, }) export class App { things: Awesome[] constructor(){ this.things = new Array(); } } @NgModule({ imports: [ BrowserModule, FormsModule ], declarations: [ App ], bootstrap: [ App ] }) export class AppModule { } export class Awesome{ name?: string; otherstuff?: string; } 
+7
angular
source share
1 answer

Do not use the index i to indicate the value of the name attribute. I am unstable when splicing elements from your array, so you need to create a unique identifier for each new thing added (I provided an example function that generates a unique identifier).

Below is the code:

 //our root app component import { Component, NgModule, VERSION } from '@angular/core' import { BrowserModule } from '@angular/platform-browser' import { FormsModule } from "@angular/forms"; @Component({ selector: 'my-app', template: ` <div> <button (click)="addEmptyItem()">+ Add new thing</button> <br /> <br /> <form> <ng-container *ngFor="let thing of things"> <input [(ngModel)]="thing.name" name="name-{{thing.id}}" id="name-{{thing.id}}" placeholder="name"/> <br /> <input [(ngModel)]="thing.otherstuff" name="other-{{thing.id}}" id="other-{{thing.id}}" placeholder="other" /> <button (click)="removeItem(thing)">Remove</button> <br /> <br /> </ng-container> </form> {{things | json}} </div> `, }) export class App { things: Awesome[] constructor() { this.things = new Array(); } removeItem(thing): void { this.things = this.things.filter(th => th.name !== thing.name); } addEmptyItem(): void { let newItem = new Awesome(); newItem.id = this.guid(); this.things.push(newItem); } private guid() { let uniqueId = Math.random().toString(36).substring(2) + (new Date()).getTime().toString(36); return uniqueId; } } @NgModule({ imports: [ BrowserModule, FormsModule ], declarations: [App], bootstrap: [App] }) export class AppModule { } export class Awesome { id?: string; name?: string; otherstuff?: string; } 
+2
source share

All Articles