A. Ranjan
A. Ranjan

Reputation: 27

View Not getting updated with change in the object property

I have this object selectedTask 2-way bound with [(ngModel)] to <ion-select> tag. However, when the changes are made to the value of fields in selectedTask, the Dom is not updated to reflect the change in value.

Here the html part:

<ion-label>Select Task</ion-label>
<ion-select [(ngModel)]="selectedTask" #A (ionChange)="updateChangedTask(false)">
      <ion-option *ngFor="let task of tasklist" [value]="task">{{task.taskName}}</ion-option>
</ion-select>
</ion-item>

the .ts file:

constructor(private changeDetector: ChangeDetectorRef ...){ }

public selectedTask = {
  taskName: "",
  taskID: "" 
};

...

changeTask(task: any){
  this.selectedTask.taskName = task.taskName;
  this.selectedTask.taskID = task.taskID;
  this.changeDetector.detectChanges();
}

The value selected in the dropdown doesn't change when changeTask() is called. I know the reason - because the reference of selectedTask doesn't change and it is not detected by Angular by it as a change. How can I make it to detect the change in object field value?

Upvotes: 0

Views: 1313

Answers (2)

mbojko
mbojko

Reputation: 14679

Don't mutate, create new object. Instead of

  this.selectedTask.taskName = task.taskName;
  this.selectedTask.taskID = task.taskID;

do for example

 this.selectedTask = Object.assign({}, task);

Another take: use primitives (so, strings), instead of objects, for values.

<ion-select [(ngModel)]="selectedTask" #A (ionChange)="updateChangedTask(false)">
      <ion-option *ngFor="let task of tasklist" [value]="task.taskID">{{task.taskName}}</ion-option>
</ion-select>

and in TS:

public selectedTask = "";

//...

changeTask(task: any) {
  this.selectedTask = task.taskID;
  this.changeDetector.detectChanges(); // may be unnecessary
}

Upvotes: 0

wentjun
wentjun

Reputation: 42516

I realise you have binded an object to the value attribute. This is incorrect, as the value attribute only accepts numbers or strings.

However, if you want to bind an object to ion-option, you should use bind the task property to ngValue instead

<ion-label>Select Task</ion-label>
  <ion-select [(ngModel)]="selectedTask" #A (ionChange)="updateChangedTask(false)">
    <ion-option *ngFor="let task of tasklist" [ngValue]="task">{{task.taskName}}</ion-option>
  </ion-select>
</ion-item> 

If you would prefer to bind a string/number instead of an entire object, you will need to make the following changes to both your component.html, and component.ts

First, you bind selectedTask to the taskID string

public selectedTask: string = '';

changeTask(task: any){
  this.selectedTask = task.taskID;
}

And then, you bind the value attribute of ion-options to task.taskID which holds a string value.

<ion-label>Select Task</ion-label>
  <ion-select [(ngModel)]="selectedTask" #A (ionChange)="updateChangedTask(false)">
    <ion-option *ngFor="let task of tasklist" [value]="task.taskID">{{task.taskName}}</ion-option>
  </ion-select>
</ion-item> 

You can choose to adopt either methods, and 2-way data binding should work accordingly.

Upvotes: 1

Related Questions