Which @angular/* package(s) are relevant/related to the feature request?
forms
Description
I'd like to use Angular's Directive Composition API (hostDirectives) to compose FormField into a custom directive. Since FormField is a standalone directive with a standard InputSignal, this seems like it should be a supported use case — but it currently doesn't work.
Use case
A common pattern when building accessible forms is to create a reusable directive that manages ARIA attributes (aria-invalid, aria-busy, aria-describedby, aria-errormessage) based on the field's validation state. Ideally, this directive would compose FormField via hostDirectives so that consumers only need a single binding per input element instead of two.
Desired behavior
The following directive composes FormField via hostDirectives and forwards its input through an alias:
import { computed, Directive, input } from '@angular/core';
import { FieldTree, FormField } from '@angular/forms/signals';
@Directive({
selector: '[formFieldAria]',
host: {
'[aria-invalid]': 'ariaInvalid()',
'[aria-busy]': 'ariaBusy()',
'[aria-describedby]': 'ariaDescribedBy()',
'[aria-errormessage]': 'ariaErrorMessage()',
},
hostDirectives: [
{ directive: FormField, inputs: ['formField: formFieldAria'] },
],
})
export class FormFieldAria<T> {
readonly formFieldAria = input.required<FieldTree<T>>();
readonly fieldDescriptionId = input<string>();
readonly ariaInvalid = computed(() => {
const state = this.formFieldAria()();
return state.touched() && !state.pending()
? state.errors().length > 0
: undefined;
});
readonly ariaBusy = computed(() => {
const state = this.formFieldAria()();
return state.pending();
});
readonly ariaDescribedBy = computed(() => {
const id = this.fieldDescriptionId();
return !id || this.ariaInvalid() ? null : id;
});
readonly ariaErrorMessage = computed(() => {
const id = this.fieldDescriptionId();
return !id || !this.ariaInvalid() ? null : id;
});
}
This would allow a clean single-binding usage in templates:
<input
type="text"
fieldDescriptionId="username-info"
[formFieldAria]="myForm.username"
/>
Current behavior
The composition does not work. FormField is not correctly applied to the host element when used via hostDirectives, so the form control registration and two-way binding that FormField normally provides do not take effect.
Current workaround
Both directives must be applied separately, which means duplicating the field binding on every input:
<input
type="text"
fieldDescriptionId="username-info"
[formField]="myForm.username"
[formFieldAria]="myForm.username"
/>
This works but is verbose and error-prone, especially in larger forms.
Minimal Reproduction
StackBlitz
Steps to reproduce
- Open the StackBlitz link above
- The
FormFieldAria directive attempts to use hostDirectives with FormField
- The form field binding does not take effect — the input is not registered with the form
Environment
Angular version: 22.0.0-next.6
Additional context
I understand that Signal Forms is still experimental. FormField is standalone and uses a standard InputSignal, so from the outside it looks like it should be compatible with hostDirectives.
Supporting this would make it much easier to build reusable, accessible form field wrappers — which feels like a natural fit for the Directive Composition API.
Proposed solution
It should be possible to compose the FormField with a custom directive, so I only have to apply one directive and pass the form field input binding.
Alternatives considered
none
Which @angular/* package(s) are relevant/related to the feature request?
forms
Description
I'd like to use Angular's Directive Composition API (
hostDirectives) to composeFormFieldinto a custom directive. SinceFormFieldis a standalone directive with a standardInputSignal, this seems like it should be a supported use case — but it currently doesn't work.Use case
A common pattern when building accessible forms is to create a reusable directive that manages ARIA attributes (
aria-invalid,aria-busy,aria-describedby,aria-errormessage) based on the field's validation state. Ideally, this directive would composeFormFieldviahostDirectivesso that consumers only need a single binding per input element instead of two.Desired behavior
The following directive composes
FormFieldviahostDirectivesand forwards its input through an alias:This would allow a clean single-binding usage in templates:
Current behavior
The composition does not work.
FormFieldis not correctly applied to the host element when used viahostDirectives, so the form control registration and two-way binding thatFormFieldnormally provides do not take effect.Current workaround
Both directives must be applied separately, which means duplicating the field binding on every input:
This works but is verbose and error-prone, especially in larger forms.
Minimal Reproduction
StackBlitz
Steps to reproduce
FormFieldAriadirective attempts to usehostDirectiveswithFormFieldEnvironment
Additional context
I understand that Signal Forms is still experimental.
FormFieldis standalone and uses a standardInputSignal, so from the outside it looks like it should be compatible withhostDirectives.Supporting this would make it much easier to build reusable, accessible form field wrappers — which feels like a natural fit for the Directive Composition API.
Proposed solution
It should be possible to compose the
FormFieldwith a custom directive, so I only have to apply one directive and pass the form field input binding.Alternatives considered
none