angularangular-materialmat-autocomplete

Angular mat-autocomplete disable input FormControl not working


I am working on a custom components library, and we have a custom autocomplete component with chips. I want to be able to disable the input control when the disabled property in config object is true. I tried to do that in ngOnInit, but it didn't work. HTML

 <div [formGroup]="group" *ngIf="config && !config.hideInput">
    <label *ngIf="config.overLabel" style="font-weight: 500;">{{ config.overLabel }}</label>
      <mat-form-field class="form-input" [appearance]="config.appearance ? config.appearance : 'standard'">
        <mat-chip-list #chipList>
          <mat-icon *ngIf="config.showIconOnAutocomplete" class="material-icons-outlined positionAbsolute" [class]="config.iconOnAutocompleteClass ? config.iconOnAutocompleteClass : ''">{{ config.showIconOnAutocomplete ? config.iconOnAutocomplete : '' }}</mat-icon>
          <mat-chip
            [class]="config.styleClass"
            *ngFor="let option of (config.value ? config.value : options); let i = index"
            selectable="true"
            removable="true"
            (removed)="remove(option.value, i)"
          >
            {{ option.value }}
            <mat-icon *ngIf="!config.removeChipIcon && option.type === 'field' && !config.disabled" matChipRemove>cancel</mat-icon>
          </mat-chip>
          <input
            #optionInput
            matInput
            type="text"
            [placeholder]="
              config.placeholder ? (config.placeholder | translate) : ''
            "
            [formControl]="optionCtrl"
            [matAutocomplete]="auto"
            [matChipInputFor]="chipList"
            [matChipInputSeparatorKeyCodes]="separatorKeysCodes"
            (matChipInputTokenEnd)="add($event)"
          />
        </mat-chip-list>
        <mat-autocomplete
          #auto="matAutocomplete"
          (optionSelected)="selected($event)"
          [displayWith]="functionFn"
        >
          <mat-option
            *ngFor="
              let option of filteredOptions | async;
              trackBy: trackByIndex
            "
            [value]="option"
          >
            {{
              config.fieldToShowAutocomplete
                ? option[config.fieldToShowAutocomplete]
                : option
            }}
          </mat-option>
        </mat-autocomplete>
        <errors-field-form
          [config]="config"
          [group]="group"
        ></errors-field-form>
      </mat-form-field>
    </div>

ts

export class FormAutocompleteMultiConditionsComponent implements Field, OnInit {
  separatorKeysCodes: number[] = [ENTER, COMMA];
  optionCtrl = new FormControl();
  @ViewChild('optionInput') optionInput!: ElementRef<HTMLInputElement>;
  config!: AutocompleteConditionsFieldConfig;
  group!: FormGroup;
  listAutocompleteCopy: {type: 'field' | 'condition' | 'operator' | 'value'; value: string; isCompound?: boolean}[] | undefined = [];
  objectKeys = Object.keys;
  options: {type: 'field' | 'condition' | 'operator' | 'value'; value: string; isCompound?: boolean}[] = [];
  filteredOptions: Observable<any[] | undefined> | undefined;
  functionFn = this.displayFn.bind(this);

  constructor() { }

  ngOnInit(): void {
    if(this.config.disabled) {
      this.optionCtrl.disable();
    }
    this.options = this.config.value;
    this.listAutocompleteCopy = this.config.listAutocomplete?.slice();
    this.filteredOptions = this.optionCtrl.valueChanges.pipe(
      startWith(''),
      debounceTime(150),
      map((value) => {
        if (value) {
          return typeof value === 'string' ||
            !this.config.fieldToShowAutocomplete
            ? value
            : value[this.config.fieldToShowAutocomplete];
        }
      }),
      map((field) =>
        field && this.listAutocompleteCopy ? this._filter(field, true) : []
      )
    );
  }
}

here is a demo https://stackblitz.com/edit/angular-ivy-uwnyev, as the ts code has more code than I have shown here.

Why disable() function in form control doesn't work?


Solution

  • You need to disable the input after the view is initialized. Otherwise, you're disabling a DOM element that hasn't been created yet. Working StackBlitz.

      ngAfterViewInit() {
        if (this.config.disabled) {
          this.optionCtrl.disable();
        }
      }