diff --git a/packages/forms/signals/src/controls/control.ts b/packages/forms/signals/src/controls/control.ts index 2ca467db539..58d61f74dfb 100644 --- a/packages/forms/signals/src/controls/control.ts +++ b/packages/forms/signals/src/controls/control.ts @@ -7,6 +7,7 @@ */ import { + afterNextRender, computed, DestroyRef, Directive, @@ -177,9 +178,11 @@ export class Control { input: HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement, ): void { const inputType = - input instanceof HTMLTextAreaElement || input instanceof HTMLSelectElement + input instanceof HTMLTextAreaElement ? 'text' - : input.type; + : input instanceof HTMLSelectElement + ? 'select' + : input.type; input.addEventListener('input', () => { switch (inputType) { @@ -227,6 +230,15 @@ export class Control { }, ); break; + case 'select': + this.maybeSynchronize( + () => this.state().value(), + (value) => { + // A select will not take a value unil the value's option has rendered. + afterNextRender(() => (input.value = value as string), {injector: this.injector}); + }, + ); + break; default: this.maybeSynchronize( () => this.state().value(), diff --git a/packages/forms/signals/test/web/control_directive.spec.ts b/packages/forms/signals/test/web/control_directive.spec.ts index 3a30438d3ca..1d5e149660f 100644 --- a/packages/forms/signals/test/web/control_directive.spec.ts +++ b/packages/forms/signals/test/web/control_directive.spec.ts @@ -22,6 +22,7 @@ import { Control, disabled, form, + hidden, max, MAX, maxLength, @@ -196,6 +197,35 @@ describe('control directive', () => { expect(cmp.f().value()).toBe('two'); }); + it('should assign correct value when unhiding select', () => { + @Component({ + imports: [Control], + template: ` + @if (!f().hidden()) { + + } + `, + }) + class TestCmp { + f = form(signal(''), (p) => hidden(p, ({value}) => value() === '')); + select = viewChild>('select'); + options = ['one', 'two', 'three']; + } + + const fix = act(() => TestBed.createComponent(TestCmp)); + const cmp = fix.componentInstance as TestCmp; + + expect(fix.componentInstance.select()).toBeUndefined(); + + act(() => cmp.f().value.set('two')); + expect(fix.componentInstance.select()).not.toBeUndefined(); + expect(fix.componentInstance.select()!.nativeElement.value).toEqual('two'); + }); + it('synchronizes with a custom value control', () => { @Component({ selector: 'my-input',