Open Closed

Regression — setDisabledState() (reactive forms disable) no longer works on Lookup components after upgrading from 10.1.1 to 10.6.1 #10904


User avatar
0
sserestyen created

Summary: After upgrading @abp/ng.core and @volo/abp.commercial.ng.ui from v10.1.1 to v10.6.1 (Angular v21 → v22), components that extend AbstractLookupSelectComponent (e.g. abp-lookup-select, likely also abp-lookup-typeahead, abp-lookup-typeahead-mtm, and the date/datetime pickers) no longer respect the disabled state set programmatically via Angular Reactive Forms (FormControl.disable() / FormGroup.disable()). Previously this worked correctly in 10.1.1.

Environment:

Angular: 22.1.7 @abp/ng.core: upgraded 10.1.1 → 10.6.1 @volo/abp.commercial.ng.ui: upgraded 10.1.1 → 10.6.1

Steps to reproduce:

  1. Bind an abp-lookup-select (or similar lookup/picker component) to a FormControl via formControlName in a reactive form, without an explicit [disabled] template binding.
  2. Call formGroup.get('xyz').disable() (or formGroup.disable()) programmatically.
  3. Observe that the lookup component's disabled visual/functional state does not update — it remains enabled, even though Angular's ControlValueAccessor.setDisabledState() is being called with true.

Expected behavior: The component should become disabled, matching the behavior in 10.1.1, consistent with the standard Angular ControlValueAccessor contract.

Root cause (identified by comparing the published 10.1.1 vs 10.6.1 bundles):

  • AbstractNgModelComponent.setDisabledState(isDisabled) is unchanged between versions — it still does this.disabled = isDisabled;.
  • However, in 10.6.1, AbstractLookupSelectComponent's constructor now contains:
this.disabledInput = input(false, { alias: 'disabled' });
this.disabled = false;
effect(() => { this.disabled = this.disabledInput(); });

This mirrors the new signal disabledInput into the plain disabled property used by the template ([abpDisabled]="disabled"). Because disabledInput only reflects the template-bound [disabled] input (not CVA state), and the component is OnPush, the plain property assignment made by setDisabledState() is no longer reliably reflected in the rendered template — it's effectively disconnected from/overwritten relative to the signal-driven effect().

  • In 10.1.1, disabled was a plain @Input() property, so setDisabledState()'s direct mutation was picked up normally by change detection.

This appears to be an unintended side effect of migrating these components to Angular signal inputs, rather than a documented/intentional breaking change — setDisabledState() itself was not modified, suggesting CVA-driven disabling was meant to keep working.

Current workaround: Explicitly bind [disabled]="expression" in the template to mirror the control's disabled condition, instead of relying solely on FormControl.disable().

Request: Please confirm whether this is a known issue, and whether a fix is planned to restore ControlValueAccessor.setDisabledState() support for lookup/picker components without requiring an explicit [disabled] template binding.

Thanks, S.

Markdown supported.
Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)

2 Answer(s)
  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent
    • What you’re seeing is consistent with a real regression introduced by the signal-based disabled input mirroring in the newer lookup/picker components: setDisabledState(true) (CVA-driven) sets the plain disabled property, but the component’s effect(() => this.disabled = this.disabledInput()) can overwrite it back to the input value (default false) and/or prevent the view from reflecting the CVA change as expected under OnPush.
    • In other words, CVA disabled state and [disabled] input are no longer merged, and the input-signal wins.

    Solution

    Recommended workaround (works today, no library patch required): bind [disabled] to the FormControl disabled state.

    Example:

    <abp-lookup-select
      formControlName="countryId"
      [disabled]="form.get('countryId')?.disabled ?? false"
      [getFn]="service.getCountryLookup"
      displayNameProp="name">
    </abp-lookup-select>
    

    If you disable/enable the whole form, you can bind to form.disabled instead:

    <abp-lookup-select
      formControlName="countryId"
      [disabled]="form.disabled"
      [getFn]="service.getCountryLookup"
      displayNameProp="name">
    </abp-lookup-select>
    

    What an ABP-side fix should look like (for the ABP team / if you patch with source):

    • The component must not continuously overwrite disabled from disabledInput() in an effect.
    • It should instead merge both sources of truth, e.g. keep two fields:
      • inputDisabled (from [disabled])
      • cvaDisabled (from setDisabledState)
      • expose disabled = inputDisabled || cvaDisabled (and ensure change detection updates)
    • Or, treat the input as the “initial value” only and let setDisabledState take over when used via forms.

    Known issue / planned fix

    I can’t verify (from the indexed support KB/docs available to me) an official ABP issue entry or release note explicitly acknowledging this specific regression in AbstractLookupSelectComponent / lookup components’ CVA disabling behavior. So I can’t definitively confirm whether it’s already tracked internally or which patch version will contain the fix.

    (Practically, given your root-cause analysis, it’s very likely unintended—because it breaks standard Angular ControlValueAccessor expectations.)

    If you have a commercial support channel, I recommend opening a ticket referencing:

    • the exact constructor snippet you posted (disabledInput = input(false...), effect(...))
    • the statement: “CVA setDisabledState is overwritten by signal input effect; should be merged”

    Reference (component API still documents disabled input)

    • https://abp.io/docs/10.6/framework/ui/angular/lookup-components

    This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    sserestyen created

    [AI-Bot] said:

    • What you’re seeing is consistent with a real regression introduced by the signal-based disabled input mirroring in the newer lookup/picker components: setDisabledState(true) (CVA-driven) sets the plain disabled property, but the component’s effect(() => this.disabled = this.disabledInput()) can overwrite it back to the input value (default false) and/or prevent the view from reflecting the CVA change as expected under OnPush.
    • In other words, CVA disabled state and [disabled] input are no longer merged, and the input-signal wins.

    Solution

    Recommended workaround (works today, no library patch required): bind [disabled] to the FormControl disabled state.

    Example:

    <abp-lookup-select 
      formControlName="countryId" 
      [disabled]="form.get('countryId')?.disabled ?? false" 
      [getFn]="service.getCountryLookup" 
      displayNameProp="name"> 
    </abp-lookup-select> 
    

    If you disable/enable the whole form, you can bind to form.disabled instead:

    <abp-lookup-select 
      formControlName="countryId" 
      [disabled]="form.disabled" 
      [getFn]="service.getCountryLookup" 
      displayNameProp="name"> 
    </abp-lookup-select> 
    

    What an ABP-side fix should look like (for the ABP team / if you patch with source):

    • The component must not continuously overwrite disabled from disabledInput() in an effect.
    • It should instead merge both sources of truth, e.g. keep two fields:
      • inputDisabled (from [disabled])
      • cvaDisabled (from setDisabledState)
      • expose disabled = inputDisabled || cvaDisabled (and ensure change detection updates)
    • Or, treat the input as the “initial value” only and let setDisabledState take over when used via forms.

    Known issue / planned fix

    I can’t verify (from the indexed support KB/docs available to me) an official ABP issue entry or release note explicitly acknowledging this specific regression in AbstractLookupSelectComponent / lookup components’ CVA disabling behavior. So I can’t definitively confirm whether it’s already tracked internally or which patch version will contain the fix.

    (Practically, given your root-cause analysis, it’s very likely unintended—because it breaks standard Angular ControlValueAccessor expectations.)

    If you have a commercial support channel, I recommend opening a ticket referencing:

    • the exact constructor snippet you posted (disabledInput = input(false...), effect(...))
    • the statement: “CVA setDisabledState is overwritten by signal input effect; should be merged”

    Reference (component API still documents disabled input)

    • https://abp.io/docs/10.6/framework/ui/angular/lookup-components

    This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

    Could this be reviewed by the support team?

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.8.0-preview. Updated on September 28, 2026, 11:44
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.