Bind <mat slide toggle> using [(ngModel)] with a string value in HTML

Viewed 23368

I have a material slide toggle button and it is two way bind with a string variable having a value "true" or "false" using [(ngModel)], the button updates the value of variable correctly when i toggle it, but for the first time when it is loaded in DOM, it always shows its state to true even if the value in the variable is "false".

<div *ngIf="agent.attributes[i].type == 'Boolean'">
  <mat-slide-toggle [checked]="agent.attributes[i].value == 'true' ? true : false" 
                  [(ngModel)]="agent.attributes[i].value">{{agent.attributes[i].value}}</mat-slide-toggle>
                </div>

this is the result

3 Answers

you are binding string value to ngModel that needs to be boolean for check, so change it to:

<div>
  <mat-slide-toggle 
      [checked]="agent.attributes[i].value === 'true' ? true : false"
      (change)="setValue( i , $event )">
      {{agent.attributes[i].value}}
  </mat-slide-toggle>
</div>

ts code:

setValue(i , e){
    if(e.checked){
        this.agent.attributes[i].value = 'true'
   }else{
        this.agent.attributes[i].value = 'false'
   }
}

DEMO

The issue with your code is that your [(ngModel)] binding is overwriting the [checked] binding. Remove the [(ngModel)] binding and you can see that the [checked] binding works just fine.

Since your value property is a string with a value of 'false' or 'true', the [(ngModel)] binding will evaluate that to true in both cases.

Ideally your value property would be a boolean. Why does it need to be a string?

With the property as a boolean you could even get rid of the [checked] binding like so:

<div *ngIf="agent.attributes[i].type == 'Boolean'">
  <mat-slide-toggle [(ngModel)]="agent.attributes[i].value">{{agent.attributes[i].value}}</mat-slide-toggle>
</div>

If it has to be of type string then you can use a getter/setter in your component like in this Stackblitz.

Related