Recommended Free Tools
Angular’s Directive Composition API lets a component or directive apply other directives to its own host element. You list those directives in the hostDirectives property of the decorator, and Angular attaches their behavior to the host without requiring the consumer to add each behavior’s selector to a template.
What the API does
Suppose you have a reusable behavior, such as keyboard-accessible menu handling or a tooltip trigger, that belongs on an existing element. Without composition, every template that needs the behavior must list its selector. With hostDirectives, a component or directive declares the behavior once, and the consumer only uses the higher-level element.
As an Amazon Associate I earn from qualifying purchases.
Two details matter from the start. First, hostDirectives is static decorator metadata. Angular resolves it at compile time; the API does not add directives at runtime. Second, when Angular applies a directive as a host directive, it ignores that directive’s selector. A selector only controls matching in templates, so a selector like [menuBehavior] has no effect on whether the directive is applied through composition.
A basic example
The simplest form lists the directive class directly in the decorator:
#1 Best Overall
@Component({
selector: 'app-menu-trigger',
template: `<ng-content />`,
hostDirectives: [MenuBehavior],
})
export class MenuTrigger {}
Every instance of <app-menu-trigger> now carries the host bindings and behavior of MenuBehavior. The consumer does not write menuBehavior anywhere. However, the plain class form does not expose any of MenuBehavior‘s inputs or outputs to the template, which is the subject of the next section.
Exposing inputs and outputs
Host-directive inputs and outputs are private by default. A host directive can have an input named menuId, but MenuTrigger does not make that input available to consumers unless it is listed in the composition metadata. Writers and developers should keep this distinction clear: “the host directive has an input” and “the component exposes that input” are different statements.
To expose bindings, replace the plain class entry with an object that names the directive and the bindings to publish:
Free tools Windows power users keep installed
One-click scans. No signup required.
Rank #2
@Component({
selector: 'app-menu-trigger',
template: `<ng-content />`,
hostDirectives: [
{
directive: MenuBehavior,
inputs: ['menuId'],
outputs: ['menuClosed'],
},
],
})
export class MenuTrigger {}
When the component should publish a clearer name, use the originalName: alias form:
hostDirectives: [
{
directive: MenuBehavior,
inputs: ['menuId: id'],
outputs: ['menuClosed: closed'],
},
]
With the aliased version, consumers bind to id and closed on the component element, for example <app-menu-trigger [id]="panelId" (closed)="onClosed()">. The original names menuId and menuClosed are not part of the component’s template API.
| Entry form in hostDirectives | Applied to the host? | Bindings visible to the consumer template? |
|---|---|---|
Plain class, for example MenuBehavior |
Yes | None |
Object with inputs: ['menuId'] |
Yes | menuId under its original name |
Object with inputs: ['menuId: id'] |
Yes | id, the alias |
Composing directives inside directives
Composition can be transitive. A host directive can itself declare hostDirectives, so a team can build layered behavior bundles: a low-level focus behavior, a menu behavior that uses it, and a component that uses the menu behavior. Each layer decides which bindings it exposes outward, so a deep bundle does not leak every internal input to the top-level component.
Rank #3
Order of execution and host binding precedence
Host directives run before the component or directive that composes them. For a single host directive, the sequence is:
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallCrashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minute- Angular instantiates the host directive.
- The host directive receives its inputs and runs its initialization work.
- The host directive’s host bindings are applied to the element.
- The owning component or directive is instantiated and applies its own host bindings.
In nested chains, the order follows the innermost directive outward. The practical result is that the owner’s host bindings win where both write the same host binding. If a host directive sets a class or attribute that your component also needs to control, set it on the owner, and check which value wins in the rendered DOM.
Dependency injection between owner and host directives
The owner and its host directives can inject one another, which lets a behavior read state from the component it is attached to. The rule for conflicts is strict: if the owner and one of its host directives both provide the same injection token, the owner’s provider takes precedence. Design shared tokens with this in mind, because the host directive will receive the owner’s value rather than its own.
Rank #4
Duplicate composition and template matches
A directive can be reached through more than one composition path, for example when two host directives both compose the same base behavior. Angular handles this in three steps:
- It de-duplicates repeated host-directive matches, so the same directive does not become multiple instances.
- It merges the binding mappings from the repeated paths into one directive instance.
- If the same directive is also matched by a template selector, Angular keeps the template match and discards the host-directive matches. The template match exposes the directive’s full public API, while host-directive matches expose only the bindings configured in
hostDirectives.
Error NG8024: conflicting aliases
Merging has one hard limit. If merged paths expose a shared input or output under different aliases, Angular reports NG8024. For example, one path exposing menuId: id and another exposing menuId: menuKey cannot both be merged into the same public binding.
Angular’s documented fixes are:
- Make every path use the same alias for the shared binding.
- Stop exposing the binding on one or both paths, so only one public name remains.
Composition or a templated component?
Composition is meant for behavior that attaches to an element that already exists. Angular’s guidance is that directives suit reusable behavior such as tooltips, autofocus, host-element classes, and event handling. If the feature must render its own markup or manage its own UI through a template, use a component, or a directive with a template, instead.
| Question | Favors hostDirectives | Favors a component or templated directive |
|---|---|---|
| Does the feature attach to an existing element? | Yes | Not required |
| Does it need its own markup or template? | No | Yes |
| How much of its API should be public? | Choose inputs and outputs explicitly | Full public API through the template |
| Does host-binding order matter? | Owner’s bindings win over host directive bindings | Not a composition concern |
| Could several paths include the same directive? | Yes, merged; alias conflicts raise NG8024 | Not applicable |
Version and standalone notes
Angular is versioned, so confirm the version in your project before copying constraints or examples. In the current official guide, a host directive may not declare standalone: false. Older versioned documentation states the requirement as standalone: true. If your project targets an earlier release, read the documentation for that exact release rather than assuming the current wording applies.
What the sources do and do not establish
The behavior described here comes from Angular’s official documentation for the Directive Composition API, as crawled in October 2026. The article does not cite adoption figures, performance measurements, or named quotations, because the official pages reviewed do not provide any.
Angular’s documentation is the reference for the behavior described above, and it is the right place to check details that change between releases.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




