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:
- 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.
- Call formGroup.get('xyz').disable() (or formGroup.disable()) programmatically.
- 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.
2 Answer(s)
-
0
- What you’re seeing is consistent with a real regression introduced by the signal-based
disabledinput mirroring in the newer lookup/picker components:setDisabledState(true)(CVA-driven) sets the plaindisabledproperty, but the component’seffect(() => this.disabled = this.disabledInput())can overwrite it back to the input value (defaultfalse) and/or prevent the view from reflecting the CVA change as expected underOnPush. - 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.disabledinstead:<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
disabledfromdisabledInput()in an effect. - It should instead merge both sources of truth, e.g. keep two fields:
inputDisabled(from[disabled])cvaDisabled(fromsetDisabledState)- expose
disabled = inputDisabled || cvaDisabled(and ensure change detection updates)
- Or, treat the input as the “initial value” only and let
setDisabledStatetake 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
ControlValueAccessorexpectations.)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
setDisabledStateis overwritten by signal input effect; should be merged”
Reference (component API still documents
disabledinput)- 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) - What you’re seeing is consistent with a real regression introduced by the signal-based
-
0
[AI-Bot] said:
- What you’re seeing is consistent with a real regression introduced by the signal-based
disabledinput mirroring in the newer lookup/picker components:setDisabledState(true)(CVA-driven) sets the plaindisabledproperty, but the component’seffect(() => this.disabled = this.disabledInput())can overwrite it back to the input value (defaultfalse) and/or prevent the view from reflecting the CVA change as expected underOnPush. - 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.disabledinstead:<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
disabledfromdisabledInput()in an effect. - It should instead merge both sources of truth, e.g. keep two fields:
inputDisabled(from[disabled])cvaDisabled(fromsetDisabledState)- expose
disabled = inputDisabled || cvaDisabled(and ensure change detection updates)
- Or, treat the input as the “initial value” only and let
setDisabledStatetake 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
ControlValueAccessorexpectations.)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
setDisabledStateis overwritten by signal input effect; should be merged”
Reference (component API still documents
disabledinput)- 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) - What you’re seeing is consistent with a real regression introduced by the signal-based