Getting Started
Angular Primitives are built entirely using Angular directives, offering a flexible and composable way to enhance your components.
There are two main ways to use them:
Let’s explore both approaches, along with some limitations and the solutions we provide.
To use a directive in a template, simply apply it to the element you want to enhance. For example, here’s how you might use the ngpSwitch
directive:
This applies the ngpSwitch
directive to the button, enabling correct behavior and accessibility. You have full control over the inputs and outputs, making this approach ideal for many use cases.
However, this method has a few limitations. Some directives — like ngpButton
— are intended to be used on specific elements (e.g. button
). Wrapping such elements in your own component can make it difficult for consumers to add attributes like type
, since you'd need to expose every possible attribute as an input manually.
To solve this, you can use host directives.
Host directives let you enhance your components by attaching existing directives at the class level. Here's how you can use ngpButton
as a host directive:
This approach allows consumers to apply attributes directly to the button
element while still benefiting from the functionality provided by the directive.
You can also expose specific inputs and outputs from the directive to your component. For example:
This lets consumers bind to the disabled
input just as if they were using ngpButton
directly.
A key limitation of host directives in Angular is that their inputs can't be set programmatically within the component. To address this, we provide two main solutions:
Some directives support configuration providers that let you set default values. For example, to configure the default expansion type for ngpAccordion
:
Consumers can still override this default by explicitly binding to the type
input.
Other directives provide a state provider, allowing you to programmatically control their inputs. For example:
Internally, all directive inputs are converted into linked signals, enabling both binding and programmatic updates.
Some features are best implemented as multiple components. Take an accordion, for example:
If you're using ngpAccordion
as a directive in the my-accordion
template, the child my-accordion-item
components won’t be able to locate it in the dependency injection tree. This is a known Angular limitation.
To solve this, Angular Primitives supports state hoisting, which allows you to share directive state between components.
To hoist the state of ngpAccordion
from the my-accordion
component:
Now, child directives like ngpAccordionItem
can correctly locate and interact with the hoisted ngpAccordion
state.
Copyright © 2025 Angular Primitives