Skip to content

Commit b5af15a

Browse files
authored
test(forms): support directive composition with FormField
Support composing the `FormField` directive with custom controls:
1 parent 0007723 commit b5af15a

2 files changed

Lines changed: 545 additions & 0 deletions

File tree

packages/forms/signals/test/web/focus.spec.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,40 @@ describe('FieldState focus behavior', () => {
7373
expect(document.activeElement).toBe(customControl.querySelector('input'));
7474
});
7575

76+
it('should delegate focus behavior to a custom control composed with a FormField', async () => {
77+
let focusCalled = false;
78+
79+
@Component({
80+
selector: 'custom-control',
81+
hostDirectives: [{directive: FormField, inputs: ['formField']}],
82+
template: '<input #input />',
83+
})
84+
class CustomControl {
85+
readonly value = model<string>();
86+
readonly input = viewChild.required<ElementRef<HTMLInputElement>>('input');
87+
focus() {
88+
focusCalled = true;
89+
this.input().nativeElement.focus();
90+
}
91+
}
92+
93+
@Component({
94+
imports: [CustomControl],
95+
template: `<custom-control [formField]="f" />`,
96+
})
97+
class TestCmp {
98+
readonly f = form(signal(''));
99+
}
100+
101+
const fixture = await act(() => TestBed.createComponent(TestCmp));
102+
const customControl = fixture.nativeElement.firstChild as HTMLInputElement;
103+
104+
await act(() => fixture.componentInstance.f().focusBoundControl());
105+
expect(focusCalled).toBeTrue();
106+
expect(document.activeElement).not.toBe(customControl);
107+
expect(document.activeElement).toBe(customControl.querySelector('input'));
108+
});
109+
76110
it('should directly focus a custom control that has no custom focus logic', async () => {
77111
@Component({
78112
selector: 'custom-control',

0 commit comments

Comments
 (0)