Mathias W
Mathias W

Reputation: 1521

How to two-way data bind in nested array in Angular

Say you have a list of tasks which in turn has a list of subtasks and you want the subtasks to be changable - How come that angular doesn't properly two-way bind the data for the subtask?

HTML

<div *ngFor="let task of tasks">
  Task value: <input [(ngModel)]="task.value">
  <br>
  <div *ngFor="let subtask of task.subtasks">
    Subtask: <input [(ngModel)]="subtask">
    </div>
</div>

{{ tasks | json }}

TS

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  tasks = [{
    value: 'Task 1',
    subtasks: ['Hello']
  }]  
}

https://stackblitz.com/edit/angular-agrzfs

Upvotes: 1

Views: 1489

Answers (2)

Nenad Radak
Nenad Radak

Reputation: 3678

You need to access index of sublist like on this code snippet

add index counter on list and access via tas.sublist[i]

   <div *ngFor="let task of tasks">
      Task value: <input [(ngModel)]="task.value">
    <br>
    <div *ngFor="let subtask of task.subtasks; let i = index">
      Subtask: <input [(ngModel)]="task.subtasks[i]">

   </div>
 </div>

{{ tasks | json }}

Upvotes: 1

Sajeetharan
Sajeetharan

Reputation: 222522

The problem here is with ngFor Each input has to have a unique name . To solve it,

use task.subtasks[index] instead of item with ngModel

Also you need to use trackByIndex inorder to avoid the slowness as it re-creates the DOM every time you change a string in your array

<div *ngFor="let subtask of task.subtasks;let index = index;trackBy:trackByIndex;">
    Subtask: <input [(ngModel)]="task.subtasks[index]">
</div>

STACKBLITZ DEMO

Upvotes: 2

Related Questions