In Angular, how can I disable the rest of the switches if one is selected?

Viewed 284

I need some help. I'm trying to disable the rest of the switches if one is selected, as only one is allowed. I've tried doing loops approach but no success. Here is my code.

HTML file

<label class="switcher switcher-success ml-3">
  <input
    type="checkbox"
    class="switcher-input"
    (change)="registerProduct(i, $event.target.checked)"
  />
  <span class="switcher-indicator">
    <span class="switcher-yes">
      <span class="ion ion-md checkmark"></span>
    </span>
    <span class="switcher-no">
      <span class="ion ion-md-close"></span>
    </span>
  </span>
</label>

Ts file

public registerProduct(index, value) {
  this.isChecked = value;
  // tslint:disable-next-line: prefer-const
  this.product = this.products[index];
  if (value) {
    this.includedProducts.push({
      EntityTypeId: '49e185d1-529c-4b7a-a6fb-245649624a14',
      EntityTypeName: 'Producto',
      EntityId: this.product.ProductId,
      EntityName: this.product.ProductName,
      Required: true,
    });
  }
}

enter image description here

3 Answers

You can simply set the value of the checked element in your object.

I assume that you have an array of elements that you then show on your table.

On each elements you can add an attribute that is the checked value as follow

// Array element
let products = [{attribute1:value1,...},{...},...] 
// If the array is created by you, just add the attribute by hand
// If you retrieve data from service or anywhere else, map all elements
products = products.map(product => { 
  return {...product, checked:false}
})

Once you have an array of elements that contains checked values, you can set them to the switches on your template

<label class="switcher switcher-success ml-3">
  <input
    type="checkbox"
    class="switcher-input"
    (change)="registerProduct(i, $event.target.checked)"
    [checked]="{{value.checked}}" <!-- Here you set the value of your product -->
  />
  <span class="switcher-indicator">
    <span class="switcher-yes">
      <span class="ion ion-md checkmark"></span>
    </span>
    <span class="switcher-no">
      <span class="ion ion-md-close"></span>
    </span>
  </span>
</label>

So then, on your change method, you can set all the values for all products as false, and set the one identified by the index as true.

I have created a stackblitz to help you to understand.

To disable all other options when one of them is selected, you could use the following:

template

<div *ngFor="let switch of switches">
  <input type="checkbox"
         [id]="switch.value"
         [disabled]="isSwitchDisabled(switch.value)"
         [(ngModel)]="switch.checked">
  <label [for]="switch.value" [innerHTML]="switch.value"></label>
</div>

controller

switches = [
  { value: 'First switch', checked: false },
  { value: 'Second switch', checked: false },
  { value: 'Third switch', checked: false },
  { value: 'Fourth switch', checked: false }
];

get selectedOptions() {
  return this.switches
    .filter(({ checked }) => checked)
    .map(({ value }) => value);
}

get isSwitchDisabled() {
  return (value: string) =>
    this.selectedOptions.length && this.selectedOptions[0] !== value;
}

My example is generic and a bit simplistic, replace <label> with your ion markup and the model with whatever it is you're currently using.
I've demonstrated the principle:

  • the [disabled] attribute needs to be dynamic. I used a getter returning a function checking the value in real time.

See it working here

If the values of your switches are not unique, you'll probably want to add unique identifiers to them (e.g: id) and use those instead of value in both the id attribute of your <input>s and in the isSwitchDisabled function.

Another aproach using only [ngModel] and (ngModel)

If you has a variable value you can use

    <div *ngFor="let switch of switches">
      <input type="checkbox"
            [id]="switch.value"
            <!--is disabled if our variable<>null and <>switch.value-->
            [disabled]="value!=null && value!=switch.value"
            <!--is true if our variable "value" is equal to switch.value-->
            [ngModel]="value==switch.value" 
            <!--we equal the variable to switchValue if is checked or null if not-->
            (ngModelChange)="value=$event?switch.value:null">
      <label [for]="switch.value" [innerHTML]="switch.value"></label>
    </div>

NOTE, you can omit the "disabled" if you want to have a serie of switch and only check one at time

Related