Ion Select doesn't work as expected

Hello guys, I’m facing an issue with ion-select.

I am using an ion-select in my Ionic Angular app to allow users to select multiple options from a list of items. I have set a maximum limit on the number of ingredients that can be selected at once. When the user tries to select more than the maximum limit, I want the list of check-box buttons to be updated accordingly. It is only getting update when the popover is closed.

I have tried using ChangeDetectorRef to force an update to the ion-select and ion-select-option components, but it doesn’t seem to work. I have also tried using NgZone to run the code in a separate zone, but that also didn’t work.

I suspect that the issue may be related to the fact that ion-select-options are rendered within a Shadow DOM, and thus are not affected by Angular’s change detection. I’m not sure how to approach this problem and would appreciate any advice or suggestions. Thank you.

Here is the HTML of my component:

<ion-select
  [(ngModel)]="selectedItems"
  (ionChange)="onSelect()"
  [multiple]="maxQuantity > 1"
  interface="popover"
  label="Select your items:"
  label-placement="floating"
>
  <ion-select-option *ngFor="let item of items" [value]="item">
    {{ item }}
  </ion-select-option>
</ion-select>

And here is the TS of my component:

export class SelectListComponent implements OnChanges {
  @Input() items: Item[];
  @Input() maxQuantity: number;
  @Output() selected = new EventEmitter<Item[]>();

  selectedItems: Item | Item[] = [];

  ngOnChanges() {
    // Reset selected items when maxQuantity changes
    this.selectedItems = [];
  }

  onSelect() {
    if (!Array.isArray(this.selectedItems)) {
      this.selectedItems = [this.selectedItems];
    } else {
      this.selectedItems = this.limitSelection(this.selectedItems);
    }

    this.selected.emit(this.selectedItems);
  }

  private limitSelection(selectedItems: Item[]): Item[] {
    if (selectedItems.length > this.maxQuantity) {
      const toRemove = selectedItems.slice(0, selectedItems.length - this.maxQuantity);
      selectedItems = selectedItems.filter(
        (item) => !toRemove.includes(item)
      );
    }

    return selectedItems;
  }
}

Did you find a solution to this? I too have a similar problem. I want to implement a “Select/deselect all” feature for a multi-value ion select. The component value is being updating correctly, but I just cannot get the display to refresh without clicking the ion-select closed and reopening. I’ve also tried forcing Angular change detection, and running in NgZone.

I too suspect the shadow dom.

Is there ANY way around this?

I’ve sort-of found a solution. It’s a bit hacky, but it will do in the absence of anything better.

  1. In the ion-select, set the “dismissOnSelect” property to “true” in [interfaceOptions] for the underlying popover.
  2. In the (ionChange) event, after resetting the select “value” property as required, set a page variable to indicate a checkbox was clicked (eg. this.optionSelected == true).
  3. For the ion-select (onDismiss) event, add a function that calls the .open() method. Only do the open if a checkbox was clicked (ie. this.optionSelected == true)
  4. Then (still in the onDismiss event), reset this.optionSelected == false, so the user can actually close the dropdown if they choose to.

What this does is briefly closes and reopens the dropdown, causing it to refresh. It flickers briefly, but it’s ok.