Angular CLI: 15.0.2
Node: 16.17.0
Package Manager: npm 8.18.0
OS: win32 x64
Angular: 15.0.2
... animations, cli, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, platform-server
... router
Package Version
---------------------------------------------------------
@angular-devkit/architect 0.1500.2
@angular-devkit/build-angular 15.0.2
@angular-devkit/core 15.0.2
@angular-devkit/schematics 15.0.2
@angular/cdk 15.0.1
@angular/material 15.0.1
@nguniversal/builders 15.0.0
@nguniversal/common 15.0.0
@nguniversal/express-engine 15.0.0
@schematics/angular 15.0.2
rxjs 7.5.7
typescript 4.8.4
Anything else relevant?
No response
Hi @leandrotassi
I can't reproduce: https://stackblitz.com/edit/angular-ivy-dqrsbv?file=src%2Fapp%2Fapp.component.ts,src%2Fapp%2Fapp.component.html
It's most probably a bug in your code. You should ask on stackoverflow or on the Angular discord, and provide a complete minimal reproduction.
Hi @jnizet
the bug occurs when using the formControlName within the formGroup.
You can look in the 'profile-editor.component.html' component and compare two controls:
<input [disabled]="true" id="street" type="text" formControlName="street" />
Does not work.
<input [disabled]="true" id="text_disable1" type="text"/>
It works
Here's an example:
https://stackblitz.com/edit/angular-cu6mce?file=src/app/profile-editor/profile-editor.component.html
You're not supposed to use disabled when binding to a form control. Look at the browser console: a message is telling you that. See https://stackblitz.com/edit/angular-ivy-dqrsbv?file=src%2Fapp%2Fapp.component.ts,src%2Fapp%2Fapp.module.ts,src%2Fapp%2Fapp.component.html for example. Open the console, and you'll see a big warning message saying:
It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
you. We recommend using this approach to avoid 'changed after checked' errors.
Example:
// Specify the disabled
property at control creation time:
form = new FormGroup({
first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
last: new FormControl('Drew', Validators.required)
// Controls can also be enabled/disabled after creation:
form.get('first')?.enable();
form.get('last')?.disable();
And that warning exists for a long time, well before Angular 15.
That [Disabled] directive actually stopped working in version 15 and I don't even get the warning in the browser console.
It was working perfectly in version 14.
But, anyway, I changed the approach to disable the controls at form creation time, as recommended by Angular.
I'm trying to reproduce the regression so I can figure out why this changed. However, it seems to behave exactly the same (odd) way in Angular 14: https://stackblitz.com/edit/angular-ivy-4ymuur?file=src/app/app.component.html
@leandrotassi , can you help me show it working in Angular 14?
marco-iscape, Adarshg315, ilyakonrad, gaetanBloch, Blackklegend, sarthikg, belbertdeon, AurelienLoyer, pratik14, johncrim, and 12 more reacted with thumbs up emoji
Machine223 reacted with thumbs down emoji
All reactions
Here is StackBlitz with reproduction: https://stackblitz.com/edit/angular-ivy-jcwird?file=src/app/app.component.html
Thanks. At the moment I have no way to test it. As soon as it works, I return the result.
I'm trying to reproduce the regression so I can figure out why this changed. However, it seems to behave exactly the same (odd) way in Angular 14: https://stackblitz.com/edit/angular-ivy-4ymuur?file=src/app/app.component.html
@leandrotassi , can you help me show it working in Angular 14?
Thanks. At the moment I have no way to test it. As soon as it works, I return the result.
I'm trying to reproduce the regression so I can figure out why this changed. However, it seems to behave exactly the same (odd) way in Angular 14: https://stackblitz.com/edit/angular-ivy-4ymuur?file=src/app/app.component.html
@leandrotassi , can you help me show it working in Angular 14?
@dylhunn
Two examples follow:
An input control using [attr.disabled] in reactive form that works in Angular 14.
https://stackblitz.com/edit/angular-ivy-ecordk?file=src/app/app.component.html
An input control using [attr.disabled] in reactive form not working in Angular 15.
https://stackblitz.com/edit/angular-ivy-pccxpj?file=src/app/app.component.ts
I'm trying to reproduce the regression so I can figure out why this changed. However, it seems to behave exactly the same (odd) way in Angular 14: https://stackblitz.com/edit/angular-ivy-4ymuur?file=src/app/app.component.html
@leandrotassi , can you help me show it working in Angular 14?
Thanks. At the moment I have no way to test it. As soon as it works, I return the result.
@e-oz
In this example using this version, the alert does not appear in the console
https://stackblitz.com/edit/angular-ivy-3dt6jt?file=src/app/app.component.html
Impacts a large percentage of users; if a workaround exists it is partial or overly painful
label
Dec 27, 2022
An input control using [attr.disabled] in reactive form that works in Angular 14.
https://stackblitz.com/edit/angular-ivy-ecordk?file=src/app/app.component.html
An input control using [attr.disabled] in reactive form not working in Angular 15.
https://stackblitz.com/edit/angular-ivy-pccxpj?file=src/app/app.component.ts
Thanks for the reproduction @leandrotassi. This is a serious regression that is likely to break a lot of forms in many apps.
The only PR touching the formControlName
directive in v15 was #43499 by @crisbeto. This could be the cause -- I'll have to write a test to check.
[Disabled] directive bug for form controls
Bug: setting [disabled]
attribute no longer works with formControlName
Dec 27, 2022
regression
Indicates than the issue relates to something that worked in a previous version
label
Dec 27, 2022
This is a workaround for a regression that was introduced in Angular v15.
See angular/angular#48350 for details.
closes #520
This is a workaround for a regression that was introduced in Angular v15.
See angular/angular#48350 for details.
closes #520
This is a workaround for a regression that was introduced in Angular v15.
See angular/angular#48350 for details.
closes #520
This is a workaround for a regression that was introduced in Angular v15.
See angular/angular#48350 for details.
closes #520
This is a workaround for a regression that was introduced in Angular v15.
See angular/angular#48350 for details.
This is a backport of 95ebfb4 to 13.x.
closes #520
This is a workaround for a regression that was introduced in Angular v15.
See angular/angular#48350 for details.
This is a backport of 95ebfb4 to 13.x.
closes #520
@dylhunn In the original question a button was used, but all the answers look like they are using an input with a FormControl, which a button can't use.
I have a component in which a button is used with the disabled attribute and this no longer works.
If I use the withConfig fix in the module where my module of the component is imported it doesn't fix it.
Any idea on a solution for disabled attribute in buttons?
We encountered this issue too when setting disabled
attribute on template driven select/input[checkbox].
We have dynamic access rights and in ngAfterViewInit() we set the attribute when in read-only mode. It worked in ang14, but with ang15 it's stopped in our template driven forms. Our reactive ones works fine. This is with latest 15.2.8
The disabled
attribute never get set. It's like the angular code removes it. Our directive sets it like this;
renderer.setAttribute(el, 'disabled', '');
I also tried this. Works with reactive, but not working in template:
renderer.setProperty(el, 'disabled', true);
I even tried this and the same. Works with reactive, but not template.
(<HTMLFieldSetElement>el).disabled = true;
The only way to get it working again was to disable the new disable functionality with:
FormsModule.withConfig({ callSetDisabledState: 'whenDisabledForLegacyCode' }),
I much prefer to have the new functionality but cannot figure out how to disable our template driven controls.
I have a different use case, and I confirm that when we call formControl.disable()
, the setDisabledState
function is no longer called in reactive forms.
We don't use [disabled]
nor [attr.disabled]
in our code, but the change affected us, in a way that doesn't seem right.
The .withConfig({ callSetDisabledState: 'whenDisabledForLegacyCode' })
works, but it means we have to do in on each of our declaration, which is ugly and inconvenient.
The use case, quite common: we have custom form components, for checkbox, radio, text field and so on.
These components declare NG_VALUE_ACCESSOR
and implement ControlValueAccessor
and use setDisabledState
to set the disabled
attribute on the native element. I know there are better ways, but that's legacy code that worked well for years.
If we disable the form group where the controls are, it works. If we disable individual components, it no longer works.
[EDIT] I tried to reproduce our problem, and I found out that my above statements are not entirely true…
My StackBlitz: https://stackblitz.com/edit/angular-xdlrrk?file=src%2Fmain.ts,src%2Fcustom-input%2Fcustom-text-input.component.ts,src%2Fcustom-input%2Fcustom-text-input.module.ts
Check the ngOnInit
part of main.ts
(similar issue if the code is in the constructor).
If I uncomment the line 35 to disable the component (initial state), it fails and the toggle doesn't work right: the form control is disabled, but setDisabledState
hasn't been called and the input state doesn't reflect the control state.
If instead I uncomment lines 37-39, it works, and that's the workaround I use in our application, instead of changing the library creating these custom components (which is our, but I don't like this hack).
Maybe I missed something in the long thread above, but is it the expected new behavior? Impossibility to start a custom form component in the disabled state? Or did I miss an official way of doing this?
Note that, as said, I don't use a disabled attribute, I do this by manipulating the form control itself, which seems to be The Good Way™.
Hi @jnizet
the bug occurs when using the formControlName within the formGroup.
You can look in the 'profile-editor.component.html' component and compare two controls:
<input [disabled]="true" id="street" type="text" formControlName="street" />
Does not work.
<input [disabled]="true" id="text_disable1" type="text"/>
It works
Here's an example:
https://stackblitz.com/edit/angular-cu6mce?file=src/app/profile-editor/profile-editor.component.html
I have the same issue so for the workaround i have used [readonly]
After update to angular 16 im trying to maintain [disabled] for radio button:
@dylhunn or anybody, can you help me with radio control value accessor?
Im trying to implement this:
and I get following errors:
error TS2322: Type 'ModuleWithProviders<FormsModule>' is not assignable to type 'readonly any[] | Type<any>'.
'imports' contains a ModuleWithProviders value, likely the result of a 'Module.forRoot()'-style call. These calls are not used to configure components and are not valid in standalone component imports - consider importing them in the application bootstrap instead.(-992012)
how to get FormsModule.withConfig in standalone component? Angular ver 16.2.0
This is also a problem, in that a warning spews to the console if you use any of the formControl
directives on a component, and the component has an @Input() disabled
. IMO the benefit of the warning in a very specific case is not worth the noise in the general case.
To state it another way: I don't have a problem with disabled
not working with formControl
directives. I have a problem that I'm getting an unnecessary warning (in dev builds) with erroneous guidance because I have an @Input() disabled
on my components, if I use a formControl
directive on those components. The name disabled
is very useful and clear, and I think it's unreasonable to assume that it can only be used on the formControl
directives.
@Component({
selector: 'ui-listbox',
providers: [ {
provide: NG_VALUE_ACCESSOR,
useClass: SelectionValueAccessor,
multi: true
export class ListboxComponent<TKey> {
@Input()
set disabled(v: boolean) {
this.focusArea.disabled = v;
this.state.disabled = v;
get disabled() {
return this.state.disabled;
// Use in template:
<ui-listbox [disabled]="disabled"
[formControl]="formControl">
gives me this warning even though nothing is wrong. Please remove the warning. I'm happy to provide a PR to remove it :)
I should add: formControl.disabled
has different meaning from a typical component's MyComponent.disabled
. When a FormControl
is disabled, it means "exclude the values from this FormControl in the parent FormGroup values". For a web page element, or UI component, a disabled
attribute typically means "appears inaccessible, cannot be focused, and value cannot be changed by user".
I think it makes sense that FormControlDirective.disabled
doesn't set FormControl.disabled
. But it's problematic to have this erroneous warning, where the options are either to a) ignore a bunch of console warnings, or b) rename disabled
to realDisabled
or something equally irritating.
See also: https://netbasal.com/disabling-form-controls-when-working-with-reactive-forms-in-angular-549dd7b42110
As temporal solution create a directive
//see I use "disable" instead of "disabled"
@Directive({
selector: '[disable]',
standalone:true
export class CustomDisabledDirective implements AfterViewInit {
_disable:boolean
@Input('disable') set _(value:boolean)
this._disable=value;
this.ngAfterViewInit();
constructor(private elementRef:ElementRef) { }
ngAfterViewInit()
if (this._disable)
this.elementRef.nativeElement.setAttribute('disabled','true')
this.elementRef.nativeElement.removeAttribute('disabled')
For use [disabled] already stopped working with angular 13 when it had a formControlName. We had to use [attr.disabled] from then on.
It seems it was mentioned in the breaking changes but I agree that it could have been worded better release note
We don't want the input to be disabled in the formGroup as validation still needs to be checked as the input gets filled in based on the other inputs from the user.
So our solution is to change in our app.module.ts ReactiveFormModule
to ReactiveFormsModule.withConfig({callSetDisabledState: 'whenDisabledForLegacyCode'})
dylhunn explains it better in his comment: #48350 (comment)
It would be nice if attr.disabled could be checked before it sets disabled on false again. but as far as I could tell that attribute was already removed and only disabled was still on the nativeElement.
i am using common component to render form after upgrade to angular 16 [attr.disabled] is not working without throwing any error.
its a huge blunder in angular upgrade
Impacts a large percentage of users; if a workaround exists it is partial or overly painful
regression
Indicates than the issue relates to something that worked in a previous version
state: confirmed
workaround2: non-obvious