From 456f02958a2938e9d8538b9610039bf28b99e095 Mon Sep 17 00:00:00 2001 From: Nick Krantz <125900171+nick-livefront@users.noreply.github.com> Date: Tue, 9 Dec 2025 09:31:12 -0600 Subject: [PATCH] account for pre-set value of an angular form before the options are set (#17872) --- .../chip-select/chip-select.component.spec.ts | 18 ++++++++++++++++++ .../src/chip-select/chip-select.component.ts | 17 +++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/libs/components/src/chip-select/chip-select.component.spec.ts b/libs/components/src/chip-select/chip-select.component.spec.ts index 3c2f71ef8d7..3a66b799652 100644 --- a/libs/components/src/chip-select/chip-select.component.spec.ts +++ b/libs/components/src/chip-select/chip-select.component.spec.ts @@ -451,6 +451,24 @@ describe("ChipSelectComponent", () => { expect(disabledMenuItem?.disabled).toBe(true); }); + + it("should handle writeValue called before options are initialized", async () => { + const testApp = fixture.componentInstance; + + component["rootTree"] = null; + + component.writeValue("opt1"); + + expect(component["pendingValue"]).toBe("opt1"); + expect(component["selectedOption"]).toBeUndefined(); + + testApp.options.set(testOptions); + fixture.detectChanges(); + await fixture.whenStable(); + + expect(component["selectedOption"]?.value).toBe("opt1"); + expect(component["pendingValue"]).toBeUndefined(); + }); }); }); diff --git a/libs/components/src/chip-select/chip-select.component.ts b/libs/components/src/chip-select/chip-select.component.ts index bf6c6fb2aad..50e462dc815 100644 --- a/libs/components/src/chip-select/chip-select.component.ts +++ b/libs/components/src/chip-select/chip-select.component.ts @@ -100,10 +100,21 @@ export class ChipSelectComponent implements ControlValueAccessor { /** Tree constructed from `this.options` */ private rootTree?: ChipSelectOption | null; + /** Store the pending value when writeValue is called before options are initialized */ + private pendingValue?: T; + constructor() { // Initialize the root tree whenever options change effect(() => { this.initializeRootTree(this.options()); + + // If there's a pending value, apply it now that options are available + if (this.pendingValue !== undefined) { + this.selectedOption = this.findOption(this.rootTree, this.pendingValue); + this.setOrResetRenderedOptions(); + this.pendingValue = undefined; + this.cdr.markForCheck(); + } }); // Focus the first menu item when menuItems change (e.g., navigating submenus) @@ -255,6 +266,12 @@ export class ChipSelectComponent implements ControlValueAccessor { /** Implemented as part of NG_VALUE_ACCESSOR */ writeValue(obj: T): void { + // If rootTree is not yet initialized, store the value to apply it later + if (!this.rootTree) { + this.pendingValue = obj; + return; + } + this.selectedOption = this.findOption(this.rootTree, obj); this.setOrResetRenderedOptions(); // OnPush components require manual change detection when writeValue() is called