Skip to content

Commit 63d8005

Browse files
cexbrayatmattrbeck
authored andcommitted
fix(forms): preserve custom-control focus context in signal forms
Fixes #67051 Store custom control focus callbacks in a wrapper so method invocation keeps the original object context. Without this, custom focus methods that access instance members throw at runtime when focusBoundControl() is called.
1 parent 0806ee3 commit 63d8005

2 files changed

Lines changed: 5 additions & 2 deletions

File tree

packages/forms/signals/src/directive/form_field_directive.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ export class FormField<T> {
251251
this.installClassBindingEffect();
252252

253253
if (bindingOptions?.focus) {
254-
this.focuser = bindingOptions.focus;
254+
this.focuser = (focusOptions?: FocusOptions) => bindingOptions.focus!(focusOptions);
255255
}
256256

257257
// Register this control on the field state it is currently bound to. We do this at the end of

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,14 @@ describe('FieldState focus behavior', () => {
4545
@Component({
4646
selector: 'custom-control',
4747
host: {'tabindex': '-1'},
48-
template: '',
48+
template: '<input #input />',
4949
})
5050
class CustomControl {
5151
readonly value = model<string>();
52+
readonly input = viewChild.required<ElementRef<HTMLInputElement>>('input');
5253
focus() {
5354
focusCalled = true;
55+
this.input().nativeElement.focus();
5456
}
5557
}
5658

@@ -68,6 +70,7 @@ describe('FieldState focus behavior', () => {
6870
await act(() => fixture.componentInstance.f().focusBoundControl());
6971
expect(focusCalled).toBeTrue();
7072
expect(document.activeElement).not.toBe(customControl);
73+
expect(document.activeElement).toBe(customControl.querySelector('input'));
7174
});
7275

7376
it('should directly focus a custom control that has no custom focus logic', async () => {

0 commit comments

Comments
 (0)