DisabledControlDirective for Reactive Forms
Reactive forms warn against the disabled attribute in templates, and a small directive is the supported way to keep disabling declarative
Did You Know — Reactive Forms warning
With Reactive Forms you may have seen:
It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to truewhen you set up this control in your component class, the disabled attribute will actually be set in the DOM foryou. We recommend using this approach to avoid 'changed after checked' errors.
Example:form = new FormGroup({first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),last: new FormControl('Drew', Validators.required)});Triggering code:
export class ReactiveFormWarningComponent implements OnInit { disabledName = false; form: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit() { this.form = this.fb.group({ name: [''], }); }}<button (click)="disabledName = !disabledName">Toggle name state</button><form [formGroup]="form"> <input class="form-control" type="text" formControlName="name" [disabled]="disabledName" /></form>
Reactive Forms ignore the native disabled attribute — the input won't actually disable.
Approach
1. Declare disabled state in the FormGroup
this.form = this.fb.group({ name: [{ value: '', disabled: false }],});2. Use FormControl.enable() / disable()
this.form.get('name').enable();this.form.get('name').disable();Both work, but neither lets you drive disable state from the template with [disabled]="disabledName" like the warning example.
Directive approach
Use a directive — DisabledControlDirective. It applies alongside formControlName or formControl. Use [disabledControl] instead of [disabled]:
import { Directive, Input } from '@angular/core';import { NgControl } from '@angular/forms';
@Directive({ selector: '([formControlName], [formControl])[disabledControl]',})export class DisabledControlDirective { @Input() set disabledControl(state: boolean) { const action = state ? 'disable' : 'enable'; this.ngControl.control[action](); }
constructor(private readonly ngControl: NgControl) {}}Template:
<form [formGroup]="form"> <input type="text" formControlName="name" [disabledControl]="disabledName" /></form>
Note
Disabled controls are omitted from FormGroup.value. Use FormGroup.getRawValue() to include disabled control values.