Search code examples
angularmaterializeangular-ngmodel

ngModel accepts just one character change in Angular 2


The picture below shows my table where the data is dynamically set. E.g., it could have 2,3,4 ... columns.

enter image description here

My html code is below: <thead> contains the title values, and tbody contains the values that can be modified.

<table class="table-conf">
    <thead>
       <tr>
           <th *ngFor="let data of jsonText[0]" style="text-align: center;">{{data}}</th>
       </tr>
    </thead>
    <tbody>
       <tr *ngFor="let data of jsonText; let i=index">
         <ng-container *ngIf="i!=0">
             <td class="padding-table" *ngFor="let dt of data; let j=index">
                 <input style="text-align: center;" [(ngModel)]="jsonText[i][j]">
             </td>
         </ng-container>
       </tr>
    </tbody>
</table>

Below is an example of jsonText variable that I iterated:

jsonText Array(6)
     0: (2) ["Task", "Hours per Day"]
     1: (2) ["Work", 11]
     2: (2) ["Eat", 2]
     3: (2) ["Commute", 2]
     4: (2) ["Watch TV", 2]
     5: (2) ["Sleep", 7]

The issue is: when I try to modify an element in the table, I can modify just one character at a time. For example: If I want to change "Eat" to "Lunch", I need to delete "Eat", then write L, click again on the input, write u, click again, etc...

Could anyone help me, please?


Solution

  • As correctly said in other answer, When you bind jsonText to ngModel then ngFor re-evaluate and you lose focus out of input.

    and when you do [(ngModel)]="dt" then ngModel can't bind to dynamically created variable. So you face this issue.

    So to make it work:

    (a) you have to apply trackBy function to your ngFor, Read

    So in HTML add trackBy function, and do binding as [(ngModel)]="data[j] , Like :

     <tr *ngFor="let data of jsonText; let i=index">
             <ng-container *ngIf="i!=0">
                 <td class="padding-table" *ngFor="let dt of data; let j=index; trackBy:customTrackBy">
                     <input style="text-align: center;" [(ngModel)]="data[j]">
                 </td>
             </ng-container>
    </tr>
    

    (b) and in your component add the function and track the index.

         customTrackBy(index: number, obj: any): any {
             return index;
         }