Bikram
Bikram

Reputation: 343

Changing [(ngModel)] value in on row of a table will affect at all rows present in the body. How to Fix it?

I have a table that got generated with *ngFor. Now Inside that table I have 2 columns and 5 rows. 1st column contains an select tag and 2nd column will show the selected value. Now the problem is when you will select any value in the select tag in any of the row, the selected value is showing up in all rows.

For Better understanding of the problem please refer https://stackblitz.com/edit/angular-43oxrc

app.component.ts

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;
  }

app.componenent.html

<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>

I need like; If you are choosing any value in 1st row then it's value should show up only in 1st row it self. It should not reflect in any other rows

Upvotes: 2

Views: 3193

Answers (3)

Sudarshana Dayananda
Sudarshana Dayananda

Reputation: 5265

You cannot do it in that way. The reason is selectedCategory is binding to all five places as it is a single value. You can do it like this.

TS

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});
    }
  }
}

HTML

<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>

StackBlitz Demo

Upvotes: 2

Drunkpunk Men
Drunkpunk Men

Reputation: 56

Try converting selectedCategory into an array of strings and replace the ngModel with a function that fills it. For example:

app.component.html

<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>

app.component.ts

    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;
      }

Upvotes: 0

moohkooh
moohkooh

Reputation: 927

because the ngmodel selectedCategory is bind for every select. Create a list of models, that are you consuming in *ngFor.

i updated your stackblitz stackblitz.com/edit/angular-xz4qft

Upvotes: 1

Related Questions