angularangular-materialangular-state-managmement

What's the proper way to manage checkbox state in Angular 8?


I have two lists, flavors and juice.

flavors = ['Apple', 'Orange', 'Banana', 'Cherry'];
juice = [];

I am using checkbox to call a method that updates the flavors in my juice list.

<mat-slide-toggle (change)="updateJuice(flavor)">Add</mat-slide-toggle>

I am including an icon to remove the flavor from the juice list that utilizes the same method.

<i class="fas fa-backspace clickable" (click)="updateJuice(flavor)"></i>

I'm not sure how best to manage the state of the checkboxes in the static list of flavors when someone removes it from their juice. Can anyone give me some advice/examples?

I was hoping I would be able to use ngModel to check the list of flavors, like this:

<mat-slide-toggle (change)="updateJuice(flavor)" [(ngModel)]="juice.indeOf(flavor) > -1">Add</mat-slide-toggle>

However, the compiler does not like this idea.

I've made a StackBlitz that shows a working example.

https://stackblitz.com/edit/list-handler?file=src/app/app.component.html

I would like to be able to make it so that the checkbox in the list of flavors becomes unchecked when someone clicks the icon that removes it from the juice list. Is there a simple way to do this?


Solution

  • In this case you want to work with Objects, to control state. Its easier and you no need to use loops, you get Object value instantly by its key. And beceuse Angular has keyvalue pipe, it becomes even easier:

    flavors = [
      'Apple', 
      'Orange',
      'Banana', 
      'Cherry'
    ];
    juice = {};
    
    updateJuice(key, event) {
      if (event.checked) {
        this.juice = {...this.juice, [key]: key }
      } else {
        delete this.juice[key];
      }
    }
    

    And now you can also bind juice Object to the state of the MatSlideToggle, so it slides off, when item deleted from juice Object:

    Pick flavors for your juice:
    <ul>
      <li *ngFor="let flavor of flavors"> 
        {{flavor}} <mat-slide-toggle [checked]="!!juice[flavor]" (change)="updateJuice(flavor, $event)">Add</mat-slide-toggle>
      </li>
    </ul>
    
    Flavors in juice:
    <ul>
      <li *ngFor="let flavor of juice | keyvalue"> 
        {{flavor.key}} <i class="fas fa-backspace clickable" (click)="updateJuice(flavor.key, $event)"></i>
      </li>
    </ul>
    

    Forked demo