From b8e71f23c976545c16cd3ca05ee6dfc6dc47788f Mon Sep 17 00:00:00 2001 From: Brian Henry <5454342+brianehenry@users.noreply.github.com> Date: Wed, 9 Feb 2022 13:50:53 -0600 Subject: [PATCH] fix: initial value in FAST select control not used when using Angular two-way binding (#5257) * Fixed value set during connect * Change files * Minor fix * Clear previous selection * Apply feedback * Addressed feedback Co-authored-by: Chris Holt --- ...-b6c2d101-5585-4492-8071-d0934d51e44e.json | 7 ++++++ .../fast-foundation/docs/api-report.md | 2 ++ .../fast-foundation/src/select/select.spec.ts | 12 ++++++++++ .../fast-foundation/src/select/select.ts | 23 +++++++++++++++++-- 4 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 change/@microsoft-fast-foundation-b6c2d101-5585-4492-8071-d0934d51e44e.json diff --git a/change/@microsoft-fast-foundation-b6c2d101-5585-4492-8071-d0934d51e44e.json b/change/@microsoft-fast-foundation-b6c2d101-5585-4492-8071-d0934d51e44e.json new file mode 100644 index 00000000000..bfafff6013c --- /dev/null +++ b/change/@microsoft-fast-foundation-b6c2d101-5585-4492-8071-d0934d51e44e.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "Fix initial select value when set early after connect", + "packageName": "@microsoft/fast-foundation", + "email": "5454342+brianehenry@users.noreply.github.com", + "dependentChangeType": "patch" +} diff --git a/packages/web-components/fast-foundation/docs/api-report.md b/packages/web-components/fast-foundation/docs/api-report.md index faad2d879c1..5a3b82313f4 100644 --- a/packages/web-components/fast-foundation/docs/api-report.md +++ b/packages/web-components/fast-foundation/docs/api-report.md @@ -2168,6 +2168,8 @@ export class Select extends FormAssociatedSelect { positionAttribute: SelectPosition; // @internal selectedIndexChanged(prev: any, next: any): void; + // (undocumented) + protected setDefaultSelectedOption(): void; setPositioning(): void; // @internal slottedOptionsChanged(prev: any, next: any): void; diff --git a/packages/web-components/fast-foundation/src/select/select.spec.ts b/packages/web-components/fast-foundation/src/select/select.spec.ts index f98cf60c561..1ce2c93e307 100644 --- a/packages/web-components/fast-foundation/src/select/select.spec.ts +++ b/packages/web-components/fast-foundation/src/select/select.spec.ts @@ -135,6 +135,18 @@ describe("Select", () => { expect(element.value).to.equal("two"); }); + it('should return the same value when the value property is set during connect', async () => { + const { element, connect, disconnect } = await setup(); + + const connectTask = connect(); + element.value = 'two'; + await connectTask; + + expect(element.value).to.equal('two'); + + await disconnect(); + }); + it("should return the same value when the value property is set after connect", async () => { const { element, connect, disconnect } = await setup(); diff --git a/packages/web-components/fast-foundation/src/select/select.ts b/packages/web-components/fast-foundation/src/select/select.ts index 7721086a022..51e60f47962 100644 --- a/packages/web-components/fast-foundation/src/select/select.ts +++ b/packages/web-components/fast-foundation/src/select/select.ts @@ -7,6 +7,7 @@ import type { ListboxOption } from "../listbox-option/listbox-option"; import { StartEnd } from "../patterns/start-end"; import type { StartEndOptions } from "../patterns/start-end"; import { applyMixins } from "../utilities/apply-mixins"; +import { Listbox } from "../listbox"; import { FormAssociatedSelect } from "./select.form-associated"; import { SelectPosition } from "./select.options"; @@ -70,7 +71,7 @@ export class Select extends FormAssociatedSelect { public set value(next: string) { const prev = `${this._value}`; - if (this.$fastController.isConnected && this.options) { + if (this.options?.length) { const selectedIndex = this.options.findIndex(el => el.value === next); const prevSelectedOption = this.options[this.selectedIndex]; @@ -229,7 +230,9 @@ export class Select extends FormAssociatedSelect { */ public formResetCallback(): void { this.setProxyOptions(); - this.setDefaultSelectedOption(); + // Call the base class's implementation setDefaultSelectedOption instead of the select's + // override, in order to reset the selectedIndex without using the value property. + super.setDefaultSelectedOption(); this.value = this.firstSelectedOption.value; } @@ -305,6 +308,22 @@ export class Select extends FormAssociatedSelect { this.updateValue(); } + protected setDefaultSelectedOption(): void { + const options: ListboxOption[] = + this.options ?? Array.from(this.children).filter(Listbox.slottedOptionFilter); + + const selectedIndex = options?.findIndex( + el => el.hasAttribute("selected") || el.selected || el.value === this.value + ); + + if (selectedIndex !== -1) { + this.selectedIndex = selectedIndex; + return; + } + + this.selectedIndex = 0; + } + /** * Reset and fill the proxy to match the component's options. *