Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to disable particular option dynamically in Angular Mat-Select

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

like image 633
Prashant Pimpale Avatar asked Jul 27 '18 05:07

Prashant Pimpale


People also ask

How do I disable options in mat select?

It is possible to disable the entire select or individual options in the select by using the disabled property on the <select> or <mat-select> and the <option> or <mat-option> elements respectively.

How do you readonly mat select?

which out put looks like: It fades out the text and the lining below get changes, is it possible to make it readonly? You can replace the mat-select form field with a input box and bind input box data with mat-select data.

How do you bind a value in mat select?

Create Select using <mat-select> To add elements to select option, we need to use <mat-option> element. To bind value with <mat-option> , we need to use value property of it. The <mat-select> has also value property to bind selected value to keep it selected. We need to use <mat-select> inside <mat-form-field> element.


3 Answers

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.

like image 61
G. Tranter Avatar answered Oct 16 '22 20:10

G. Tranter


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>

like image 2
Nikhil Kamani Avatar answered Oct 16 '22 20:10

Nikhil Kamani


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) })
)}
like image 1
Divek John Avatar answered Oct 16 '22 20:10

Divek John