Search code examples
angulardrop-down-menuangular-reactive-formsdisable

Angular disable dropdown menu in Reactive Form until value in another dropdown menu has been set


I want a dropdown menu "subcategories" to be disabled with a grey background (and no possibility to open the dropdown menu with the defined placeholder) until the user has selected a value from the dropdownmenu "categories". I'm working with reactive forms. My lists "categories" and "subcategories" are hardcoded in the component class and I have a list selectedSubcategories declared on top to retain the list of subcategories based on the chosen category.

In the template-driven approach, I managed to disable this dropdown by using the [disabled] attribute.

My html for the dropdown menu "categories":

<select class="form-control" (change)="selectChangeCategory($event)">
          <option disabled selected>Select...</option>
          <option *ngFor="let category of categories">
            {{category.name}}
          </option>
        </select>

The selectChangeCategory method who keeps track of the value chosen in the dropdown menu "categories":

selectChangeCategory(event: any){
    this.selectedCategory = event.target.value;
    this.selectedSubcategories = this.selectSubcategory(this.selectedCategory);
  }

The selectSubcategory method who returns the right list of subcategories:

selectSubcategory(selectedCategory: string){
  if(selectedCategory == "Category 1"){
    this.selectedSubcategories = this.subcategoriesCategory1;
  }
  else if(selectedCategory == "Category 2"){
    this.selectedSubcategories = this.subcategoriesCategory2;
  }
  else{
    this.selectedSubcategories = [{name: 'empty!'}];
  }
  return this.selectedSubcategories;
  }

My html for the dropdown menu "subcategories":

<select class="form-control" (change)="selectSubcategory(selectedCategory)" value="subcategory.name" [disabled]="selectedCategory===''">
          <option disabled selected >Select...</option>
          <option *ngFor="let subcategory of selectedSubcategories">
            {{subcategory.name}}
          </option>
        </select>

The [disabled]="selectedCategory===''" works perfectly in the template-driven approach. The dropdown menu "subcategories" has a nice grey background and is disabled until the user selects a category. In the reactive form approach, this code fails. I manage to display only subcategories when a category has been chosen, but you can still open the dropdown menu of "subcategories" and see the "Select..." label.

Edit: this is my code in the ngOnchanges() method:

ngOnChanges(){
    this.selectedSubcategories = this.selectSubcategory(this.selectedCategory);
  }

I really appreciate any help here.


Solution

  • in reactive form you should disable controls in one of these forms

    FormControl({value: '', disabled: true})
    

    or reactivly

    control.disable() 
    control.enable()
    

    because in template driven form you actually set disable attribute on control. or if you want a simpler solution you can create a custom directive like this

    import { NgControl } from '@angular/forms';
    
    @Directive({
      selector: '[disableControl]'
    })
    export class DisableControlDirective {
    
      @Input() set disableControl( condition : boolean ) {
        const action = condition ? 'disable' : 'enable';
        this.ngControl.control[action]();
      }
    
      constructor( private ngControl : NgControl ) {
      }
    
    }
    

    This directive does exactly disable attribute in context of reactive form