From fe35cbd320d0b8784061141a86e42e575b7331c2 Mon Sep 17 00:00:00 2001 From: Ben Hong Date: Mon, 8 Jun 2026 13:48:32 -0400 Subject: [PATCH] docs: smooth out directives guide narrative flow (#69822) PR Close #69822 --- .../guide/directives/attribute-directives.md | 205 +++++++++--------- adev/src/content/guide/directives/overview.md | 135 ++++-------- 2 files changed, 149 insertions(+), 191 deletions(-) diff --git a/adev/src/content/guide/directives/attribute-directives.md b/adev/src/content/guide/directives/attribute-directives.md index d6ac24320bb..3f36ebbe16d 100644 --- a/adev/src/content/guide/directives/attribute-directives.md +++ b/adev/src/content/guide/directives/attribute-directives.md @@ -1,38 +1,95 @@ # Attribute directives -Change the appearance or behavior of DOM elements and Angular components with attribute directives. +Attribute directives change the appearance or behavior of DOM elements and Angular components. + +## Built-in attribute directives + +Angular includes several built-in attribute directives for common tasks: + +| Common directives | Details | +| :----------------------------------------------------- | :------------------------------------------------- | +| [`NgClass`](#adding-and-removing-classes-with-ngclass) | Adds and removes a set of CSS classes. | +| [`NgStyle`](#setting-inline-styles-with-ngstyle) | Adds and removes a set of HTML styles. | +| [`NgModel`](guide/forms/template-driven-forms) | Adds two-way data binding to an HTML form element. | + +HELPFUL: Built-in directives use only public APIs. They do not have special access to any private APIs that other directives can't access. + +### Adding and removing classes with `NgClass` + +Add or remove multiple CSS classes simultaneously by binding `[ngClass]` to an expression. To use `NgClass`, add it to the component's `imports` list: + +```angular-ts +import {NgClass} from '@angular/common'; + +@Component({ + /* ... */ + imports: [NgClass], +}) +export class AppComponent {} +``` + +To toggle a single class, bind `[ngClass]` to a conditional expression that returns the class name. In this example, `ngClass` applies the `special` class when `isSpecial` is `true`: + + + +To toggle several classes at once, bind `[ngClass]` to an object. Each key is a class name, and Angular adds the class when its value is truthy and removes it when its value is falsy: + +```angular-html +
+ This div's classes reflect the current component state. +
+``` + +HELPFUL: To add or remove a _single_ class, use [class binding](/guide/templates/binding#css-class-and-style-property-bindings) rather than `NgClass`. + +### Setting inline styles with `NgStyle` + +Set multiple inline styles simultaneously by binding `[ngStyle]` to an object. To use `NgStyle`, add it to the component's `imports` list: + +```angular-ts +import {NgStyle} from '@angular/common'; + +@Component({ + /* ... */ + imports: [NgStyle], +}) +export class AppComponent {} +``` + +Each key in the object is a CSS property name and each value is the style to apply: + +```angular-html +
+ This div's styles reflect the current component state. +
+``` + +HELPFUL: To add or remove a _single_ style, use [style bindings](guide/templates/binding#css-class-and-style-property-bindings) rather than `NgStyle`. ## Building an attribute directive -This section walks you through creating a highlight directive that sets the background color of the host element to yellow. +A custom attribute directive is a class with the `@Directive()` decorator. The decorator's `selector` defines the attribute that applies the directive. By convention, custom selectors use a prefix such as `app` and wrap the name in square brackets to form an attribute selector: -1. To create a directive, use the CLI command [`ng generate directive`](tools/cli/schematics). +```angular-ts +import {Directive} from '@angular/core'; - ```shell - ng generate directive highlight - ``` +@Directive({ + selector: '[appHighlight]', +}) +export class HighlightDirective {} +``` - The CLI creates `src/app/highlight.directive.ts`, a corresponding test file `src/app/highlight.directive.spec.ts`. +HELPFUL: The CLI command [`ng generate directive`](tools/cli/schematics) scaffolds a directive along with its test file. - ```angular-ts - import {Directive} from '@angular/core'; +To change the host element, a directive needs a reference to it. Inject [`ElementRef`](guide/di) to reach the element through its `nativeElement` property. This directive sets the background to yellow when Angular creates it: - @Directive({ - selector: '[appHighlight]', - }) - export class HighlightDirective {} - ``` - - The `@Directive()` decorator's configuration property specifies the directive's CSS attribute selector, `[appHighlight]`. - -1. Import `ElementRef` and `inject` from `@angular/core`. - `ElementRef` grants direct access to the host DOM element through its `nativeElement` property. - -1. Use [`inject`](guide/di) to obtain a reference to the host DOM element, the element to which you apply `appHighlight`. - -1. Add logic to the `HighlightDirective` class that sets the background to yellow. - - + IMPORTANT: Directives _do not_ support namespaces. @@ -42,104 +99,43 @@ IMPORTANT: Directives _do not_ support namespaces. ## Applying an attribute directive -To use the `HighlightDirective`, add a `

` element to the HTML template with the directive as an attribute. +To apply the directive, add its selector as an attribute on an element: -Angular creates an instance of the `HighlightDirective` class, which uses `inject(ElementRef)` to get a reference to the `

` element and set its background style to yellow. +Angular creates an instance of `HighlightDirective` for that `

` element, injects a reference to the element, and sets its background to yellow. ## Handling user events -This section shows you how to detect when a user mouses into or out of the element and to respond by setting or clearing the highlight color. - -1. Configure host event bindings using the `host` property in the `@Directive()` decorator. - - - -1. Add two event handler methods, and map host element events to them via the `host` property. - - - -Subscribe to events of the DOM element that hosts an attribute directive (the `

` in this case) by configuring event listeners on the directive's [`host` property](guide/components/host-elements#binding-to-the-host-element). - -HELPFUL: The handlers delegate to a helper method, `highlight()`, that sets the color on the host DOM element, `el`. - -The complete directive is as follows: +To respond to user interaction, bind host element events to handler methods through the `host` property of the `@Directive()` decorator. The following directive highlights the host element while the pointer is over it and clears the highlight when the pointer leaves: -The background color appears when the pointer hovers over the paragraph element and disappears as the pointer moves out. +The `host` property maps the `mouseenter` and `mouseleave` events to the `onMouseEnter()` and `onMouseLeave()` methods, which delegate to a `highlight()` helper that sets the background color on the host element. For more on host event bindings, see [binding to the host element](guide/components/host-elements#binding-to-the-host-element). Second Highlight -## Passing values into an attribute directive +## Accepting input values -This section walks you through setting the highlight color while applying the `HighlightDirective`. +Like components, directives accept inputs through the [`input()`](guide/components/inputs) function. Give an input the same name as the selector so that a single binding both applies the directive and passes a value to it: -1. In `highlight.directive.ts`, import `input` from `@angular/core`. + - +Read the input by calling its signal, and fall back to a default when no value is bound: -1. Add an `appHighlight` `input` property. + - +In the template, bind the value to the selector. Because the input shares the selector's name, `[appHighlight]` both applies the directive and sets its value: - The `input()` function adds metadata to the class that makes the directive's `appHighlight` property available for binding. + -1. In `app.component.ts`, add a `color` property to the `AppComponent`. +A directive can declare more than one input. The following directive adds a `defaultColor` input, then falls back through `appHighlight`, `defaultColor`, and finally `red`: - + -1. To simultaneously apply the directive and the color, use property binding with the `appHighlight` directive selector, setting it equal to `color`. +Bind both inputs on the same element. Because `defaultColor` takes a static string rather than a dynamic expression, it doesn't need square brackets: - - - The `[appHighlight]` attribute binding performs two tasks: - - Applies the highlighting directive to the `

` element - - Sets the directive's highlight color with a property binding - -### Setting the value with user input - -This section guides you through adding radio buttons to bind your color choice to the `appHighlight` directive. - -1. Add markup to `app.component.html` for choosing a color as follows: - - - -2. Revise the `AppComponent.color` so that it has no initial value. - - - -3. In `highlight.directive.ts`, revise `onMouseEnter` method so that it first tries to highlight with `appHighlight` and falls back to `red` if `appHighlight` is `undefined`. - - -4. Serve your application to verify that the user can choose the color with the radio buttons. - - Animated gif of the refactored highlight directive changing color according to the radio button the user selects - -## Binding to a second property - -This section guides you through configuring your application so the developer can set the default color. - -1. Add a second `input()` property to `HighlightDirective` called `defaultColor`. - - - -2. Revise the directive's `onMouseEnter` so that it first tries to highlight with the `appHighlight`, then with the `defaultColor`, and falls back to `red` if both properties are `undefined`. - - - -3. To bind to the `AppComponent.color` and fall back to "violet" as the default color, add the following HTML. - In this case, the `defaultColor` binding doesn't use square brackets, `[]`, because the value is a static string, not a dynamic expression. - - - - As with components, you can add multiple directive property bindings to a host element. - -The default color is red if there is no default color binding. -When the user chooses a color the selected color becomes the active highlight color. - -Animated gif of final highlight directive that shows red color with no binding and violet with the default color set. When user selects color, the selection takes precedence. + ## Deactivating Angular processing with `NgNonBindable` @@ -157,3 +153,10 @@ In the following example, the `appHighlight` directive is still active but Angul If you apply `ngNonBindable` to a parent element, Angular disables interpolation and binding of any sort, such as property binding or event binding, for the element's children. + +## What's next + + + + + diff --git a/adev/src/content/guide/directives/overview.md b/adev/src/content/guide/directives/overview.md index a30d7929df2..a640831663b 100644 --- a/adev/src/content/guide/directives/overview.md +++ b/adev/src/content/guide/directives/overview.md @@ -1,118 +1,73 @@ - -Directives are classes that add additional behavior to elements in your Angular applications. + +Directives add behavior to elements and components in your Angular applications. -Use Angular's built-in directives to manage forms, lists, styles, and what users see. +A directive can change how an element looks, how it behaves, or how it fits into the DOM. Angular ships with several built-in directives, and you can write your own. -The different types of Angular directives are as follows: +## When to use a directive -| Directive Types | Details | -| :--------------------------------------------------------------- | :-------------------------------------------------------------------------------- | -| [Components](guide/components) | Used with a template. This type of directive is the most common directive type. | -| [Attribute directives](#built-in-attribute-directives) | Change the appearance or behavior of an element, component, or another directive. | -| [Structural directives](/guide/directives/structural-directives) | Change the DOM layout by adding and removing DOM elements. | +Directives are most effective when they encapsulate **reusable** behavior that you want to apply to an existing element or component. -This guide covers built-in [attribute directives](#built-in-attribute-directives). +Common examples include: -## Built-in attribute directives +- Applying the same appearance or behavior across many elements, such as autofocus or a tooltip. +- Reading from or writing to the host element's DOM, attributes, or classes. +- Adding behavior to a component you don't own without changing its source. -Attribute directives listen to and modify the behavior of other HTML elements, attributes, properties, and components. +If you need to render your own markup or manage a piece of UI with its own template, reach for a [component](guide/components) rather than a directive. -The most common attribute directives are as follows: +## A quick example -| Common directives | Details | -| :----------------------------------------------------- | :------------------------------------------------- | -| [`NgClass`](#adding-and-removing-classes-with-ngclass) | Adds and removes a set of CSS classes. | -| [`NgStyle`](#setting-inline-styles-with-ngstyle) | Adds and removes a set of HTML styles. | -| [`NgModel`](guide/forms/template-driven-forms) | Adds two-way data binding to an HTML form element. | +Suppose you want elements to highlight when the user hovers over them, changing their background color to yellow. Rather than repeat the same event-handling logic on every element, you can package that behavior in a directive and apply it wherever you need it. -HELPFUL: Built-in directives use only public APIs. They do not have special access to any private APIs that other directives can't access. - -## Adding and removing classes with `NgClass` - -Add or remove multiple CSS classes simultaneously with `ngClass`. - -HELPFUL: To add or remove a _single_ class, use [class binding](/guide/templates/binding#css-class-and-style-property-bindings) rather than `NgClass`. - -### Import `NgClass` in the component - -To use `NgClass`, add it to the component's `imports` list. +The following `appHighlight` directive sets the host element's background color when the pointer enters and clears it when the pointer leaves: ```angular-ts -import {NgClass} from '@angular/common'; +import {Directive, ElementRef, inject} from '@angular/core'; -@Component({ - /* ... */ - imports: [NgClass], +@Directive({ + selector: '[appHighlight]', + host: { + '(mouseenter)': 'onMouseEnter()', + '(mouseleave)': 'onMouseLeave()', + }, }) -export class AppComponent {} +export class HighlightDirective { + private el = inject(ElementRef); + + onMouseEnter() { + this.el.nativeElement.style.backgroundColor = 'yellow'; + } + + onMouseLeave() { + this.el.nativeElement.style.backgroundColor = ''; + } +} ``` -### Using `NgClass` with an expression +Apply the directive by adding its selector as an attribute on an element: -On the element you'd like to style, add `[ngClass]` and set it equal to an expression. -In this case, `isSpecial` is a boolean set to `true` in `app.component.ts`. -Because `isSpecial` is true, `ngClass` applies the class of `special` to the `

`. - - - -### Using `NgClass` with a method - -1. To use `NgClass` with a method, add the method to the component class. - In the following example, `setCurrentClasses()` sets the property `currentClasses` with an object that adds or removes three classes based on the `true` or `false` state of three other component properties. - - Each key of the object is a CSS class name. - If a key is `true`, `ngClass` adds the class. - If a key is `false`, `ngClass` removes the class. - - - -1. In the template, add the `ngClass` property binding to `currentClasses` to set the element's classes: - - - -For this use case, Angular applies the classes on initialization and in case of changes caused by reassigning the `currentClasses` object. -The full example calls `setCurrentClasses()` initially with `ngOnInit()` when the user clicks on the `Refresh currentClasses` button. -These steps are not necessary to implement `ngClass`. - -## Setting inline styles with `NgStyle` - -HELPFUL: To add or remove a _single_ style, use [style bindings](guide/templates/binding#css-class-and-style-property-bindings) rather than `NgStyle`. - -### Import `NgStyle` in the component - -To use `NgStyle`, add it to the component's `imports` list. - -```angular-ts -import {NgStyle} from '@angular/common'; - -@Component({ - /* ... */ - imports: [NgStyle], -}) -export class AppComponent {} +```angular-html +

Highlight me!

``` -Use `NgStyle` to set multiple inline styles simultaneously, based on the state of the component. +Every element that carries the `appHighlight` attribute gains the same hover behavior, with the logic defined in one place. -1. To use `NgStyle`, add a method to the component class. +## Types of directives - In the following example, `setCurrentStyles()` sets the property `currentStyles` with an object that defines three styles, based on the state of three other component properties. +Angular has two primary types of directives: - - -1. To set the element's styles, add an `ngStyle` property binding to `currentStyles`. - - - -For this use case, Angular applies the styles upon initialization and in case of changes. -To do this, the full example calls `setCurrentStyles()` initially with `ngOnInit()` and when the dependent properties change through a button click. -However, these steps are not necessary to implement `ngStyle` on its own. +| Directive type | Details | +| :-------------------------------------------------------------- | :-------------------------------------------------------------------------------- | +| [Attribute directives](guide/directives/attribute-directives) | Change the appearance or behavior of an element, component, or another directive. | +| [Structural directives](guide/directives/structural-directives) | Change the DOM layout by adding and removing DOM elements. | ## What's next +Learn more about each type of directive in the following guides. + - - + +