添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement . We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account 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
  • Yes, this behavior used to work in the previous version
  • The previous version in which this bug was not present was

    Angular 14

    Description

    When upgrading from Angular 14 to Angular 15 the [Disabled] directive of form controls stopped working.

    Is this a bug or did something change?

    I'm using version 15.0.2

    Minimal Reproduction

    <button type="button" id="btnAddPeopleEditor" class="btn btn-success btn-sm" (click)="addPeople(1)"
    [disabled]="disabledEditEditor || (habilitarControle(isReadOnly) == 'true')">

    Exception or Error

    No error occurs. It simply stopped working.
    

    Your Environment

    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