Skip to content
corpus.web

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

Baseline Angular 22.1.1
Kind Concept
View source

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:

ts
export class ReactiveFormWarningComponent implements OnInit {  disabledName = false;  form: FormGroup;
  constructor(private fb: FormBuilder) {}
  ngOnInit() {    this.form = this.fb.group({      name: [''],    });  }}
html
<button (click)="disabledName = !disabledName">Toggle name state</button><form [formGroup]="form">  <input    class="form-control"    type="text"    formControlName="name"    [disabled]="disabledName"  /></form>

DisabledControlDirective to disable Reactive Form control
DisabledControlDirective to disable Reactive Form control

Reactive Forms ignore the native disabled attribute — the input won't actually disable.

Approach

1. Declare disabled state in the FormGroup

ts
this.form = this.fb.group({  name: [{ value: '', disabled: false }],});

2. Use FormControl.enable() / disable()

ts
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 directiveDisabledControlDirective. It applies alongside formControlName or formControl. Use [disabledControl] instead of [disabled]:

ts
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:

html
<form [formGroup]="form">  <input type="text" formControlName="name" [disabledControl]="disabledName" /></form>

DisabledControlDirective to disable Reactive Form control
DisabledControlDirective to disable Reactive Form control

Note

Disabled controls are omitted from FormGroup.value. Use FormGroup.getRawValue() to include disabled control values.

Source code

https://stackblitz.com/edit/angular-disable-reactive-form-control-directive?file=src/app/disabled-control.directive.ts

0%