How to disable particular option dynamically in Angular Mat-Select
Asked Answered
C

5

18

I have a list with an object has name and id properties:

[
  {
    "name": "open",
    "id": "1"
  },
  {
    "name": "inprogress",
    "id": "2"
  },
  {
    "name": "close",
    "id": "3"
  }
]

And using MatSelect with *ngFor to iterate over an array and bind the current status with select using [(ngModel)].

Expected output:

If the current status is inprogress then disable open option

StackBlitz Example

Contumacy answered 27/7, 2018 at 5:45 Comment(0)
F
26

The example doesn't work properly because selected is bound with [value]="topping.id", but the logic uses selected.id which doesn't exist except on startup because you are initializing selected with a topping object.

Also, the logic [disabled]="topping.id < selected.id" is possibly flawed because it also disables inprogress when close is selected - you might want that - I'm not sure - but you only said you wanted to disable open when inprogress is selected.

Either use [value]="topping":

<mat-form-field>
    <mat-select placeholder="Toppings" [(ngModel)]="selected" [formControl]="toppings">
        <mat-option *ngFor="let topping of list" [value]="topping" [disabled]="selected.id === '2' && topping.id === '1'">{{topping.name}}</mat-option>
    </mat-select>
</mat-form-field>

Or change the logic and initialization of selected:

selected: any =  '2';

<mat-form-field>
    <mat-select placeholder="Toppings" [(ngModel)]="selected" [formControl]="toppings">
        <mat-option *ngFor="let topping of list" [value]="topping.id" [disabled]="selected === '2' && topping.id === '1'">{{topping.name}}</mat-option>
    </mat-select>
</mat-form-field>

Update for Angular v6/7 and later

Use [(value)] instead of [(ngModel)]. Support for using the ngModel input property and ngModelChange event with reactive form directives has been deprecated in Angular v6 and is removed in Angular v7.

Fief answered 27/7, 2018 at 14:2 Comment(4)
should I use status name in If?Contumacy
I am using the [(ngModel)]="obj.status" which contains name and code in status objectContumacy
So the status which come in obj.status is inprogress then open option will be only disable that my requirementContumacy
If your model uses the object {name, code} then follow the top example but replace topping with status (or obj.status I am not sure) and id with code I think.Fief
M
3

if user can select multiple options we dont really need ngModel as well, below is my solution to disable certain option on select of some different option in angular material mat-select.

//toppings is a form control name for mat-select
this.toppings.valueChanges.subscribe((selection) => { 

this.selected = '';

//includes because in case we are using multi selection we will receive selection as array

if(selection.includes('inprogress')) // if index instead of name use index value
this.selected = 'inprogress' // selected is globally defined variable
)}

checkUserSelection(topping){

if(this.selected === 'inprogress' && topping === 'open')"{
return true;
}
return false
}

----------------- Html Code ---------------------

<mat-form-field>
<mat-select placeholder="Toppings" 
[formControl]="toppings">

<mat-option *ngFor="let topping of list" 
<!-- Added null check for the topping field -->
[value]="topping?.id" 
[disabled]="checkUserSelection(topping)"
</mat-option>
</mat-select>

Mori answered 26/12, 2019 at 13:27 Comment(0)
I
2

I did it like this in HTML

      <mat-select [(ngModel)]="algorithm">
        <mat-option
          *ngFor="let algo of algos"
          [value]="algo.name"
          [disabled]="!algo.allow">
          {{ algo }}
        </mat-option>
      </mat-select>

and in ts

 algos = ['FIFO', 'LIFO'];
    somefunctionCall(){ // Map the Array
        const fifoAllowed = false;
        isAllowed = (algo) => algo === 'FIFO' ? fifoAllowed : true;
        this.algos = this.algos.map(a => ({ name: a, allow: isAllowed(a) })
)}
Ironing answered 15/11, 2020 at 14:18 Comment(0)
C
1

You can disabled option in mat-select by putting condition as below :

<mat-form-field>
  <mat-select placeholder="Toppings" [(ngModel)]="selected" [formControl]="toppings">
    <mat-option *ngFor="let topping of list" [value]="topping.id" [disabled]="topping.id < selected.id">{{topping.name}}</mat-option>
  </mat-select>
</mat-form-field>

<br> 
Classics answered 27/7, 2018 at 9:22 Comment(6)
by defualt is the status is inprogress then open should be disbledContumacy
I have checked in stack Blitz and it is working fine.Where is creating issue?Classics
This doesn't really work - the logic from the original code is wrong.Fief
By default selected has value 2 (in progress) so open status (value = 1) is disabled because it is less than selected value.Classics
If you paste this code into the stackblitz example, it does not work at all.Fief
Please, always add a null check to your template fields so that your template won't break in any circumstance : topping?.idGasparo
C
0
 regexStr = '^[a-zA-Z0-9_]*$';
  @Input() isAlphaNumeric: boolean;

  constructor(private el: ElementRef) { }


  @HostListener('keypress', ['$event']) onKeyPress(event) {
    return new RegExp(this.regexStr).test(event.key);
  }

  @HostListener('paste', ['$event']) blockPaste(event: KeyboardEvent) {
    this.validateFields(event);
  }

  validateFields(event) {
    setTimeout(() => {

      this.el.nativeElement.value = this.el.nativeElement.value.replace(/[^A-Za-z ]/g, '').replace(/\s/g, '');
      event.preventDefault();

    }, 100)
  }
Charter answered 29/2 at 14:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.