angular-cn/aio/content/guide/attribute-directives.md

175 lines
8.9 KiB
Markdown
Raw Normal View History

# Attribute directives
2017-04-01 01:57:13 +02:00
With attribute directives, you can change the appearance or behavior of DOM elements and Angular components.
2017-04-01 01:57:13 +02:00
<div class="alert is-helpful">
2019-06-05 13:58:31 +08:00
See the <live-example></live-example> for a working example containing the code snippets in this guide.
</div>
## Building an attribute directive
This section walks you through creating a highlight directive that sets the background color of the host element to yellow.
1. To create a directive, use the CLI command [`ng generate directive`](cli/generate).
<code-example language="sh" class="code-shell">
ng generate directive highlight
</code-example>
The CLI creates `src/app/highlight.directive.ts`, a corresponding test file `src/app/highlight.directive.spec.ts`, and declares the directive class in the `AppModule`.
The CLI generates the default `src/app/highlight.directive.ts` as follows:
<code-example path="attribute-directives/src/app/highlight.directive.0.ts" header="src/app/highlight.directive.ts"></code-example>
The `@Directive()` decorator's configuration property specifies the directive's CSS attribute selector, `[appHighlight]`.
2017-04-01 01:57:13 +02:00
1. Import `ElementRef` from `@angular/core`.
`ElementRef` grants direct access to the host DOM element through its `nativeElement` property.
1. Add `ElementRef` in the directive's `constructor()` to [inject](guide/dependency-injection) a reference to the host DOM element, the element to which you apply `appHighlight`.
2017-04-01 01:57:13 +02:00
1. Add logic to the `HighlightDirective` class that sets the background to yellow.
<code-example path="attribute-directives/src/app/highlight.directive.1.ts" header="src/app/highlight.directive.ts"></code-example>
<div class="alert is-helpful">
Directives _do not_ support namespaces.
<code-example path="attribute-directives/src/app/app.component.avoid.html" header="src/app/app.component.avoid.html (unsupported)" region="unsupported"></code-example>
2017-04-10 16:51:13 +01:00
</div>
{@a apply-directive}
## Applying an attribute directive
1. To use the `HighlightDirective`, add a `<p>` element to the HTML template with the directive as an attribute.
<code-example path="attribute-directives/src/app/app.component.1.html" header="src/app/app.component.html" region="applied"></code-example>
Angular creates an instance of the `HighlightDirective` class and injects a reference to the `<p>` element into the directive's constructor, which sets the `<p>` element's background style to yellow.
{@a respond-to-user}
2017-04-01 01:57:13 +02:00
## 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. Import `HostListener` from '@angular/core'.
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" header="src/app/highlight.directive.ts (imports)" region="imports"></code-example>
1. Add two event handlers that respond when the mouse enters or leaves, each with the `@HostListener()` decorator.
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" header="src/app/highlight.directive.ts (mouse-methods)" region="mouse-methods"></code-example>
With the `@HostListener()` decorator, you can subscribe to events of the DOM element that hosts an attribute directive, the `<p>` in this case.
The handlers delegate to a helper method, `highlight()`, that sets the color on the host DOM element, `el`.
The complete directive is as follows:
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" header="src/app/highlight.directive.ts"></code-example>
The background color appears when the pointer hovers over the paragraph element and disappears as the pointer moves out.
<div class="lightbox">
docs(aio): image sweep (#16609) * fix(aio): allow code blocks to clear floated images Previously the negative margin on the code headings were causing floated images to overlay the start of a code block. Now all code block successfully clear all floated elements. * feat(aio): add a `.clear` class for clearing floating images * fix(aio): tidy up image styles The css rules for `img.right` and `img.left` allow authors easy access to floating an image on the left or right, respectively. The `.image-display` rule which was always found on a figure has been simplified so that all figures have this styling. It is very unlikely that a figure will be used outside the content area; and at this time it seems like `figure` is as good an indicator that we want this kind of styling as anything. Now that images are all tagged with width and height values, we cannot assume to modify these dimensions via CSS as it can cause the image to lose its correct proportions. Until we find a better solition we must set `height` to `auto` when the screen width is below 1300px to ensure that these images maintain their proportions as they get shrunk to fit. * docs(aio): general tidy up of image HTML in guides Previously, the guides have a lot of inline image styling and unnecessary use of the `image-display` css class. Images over 700px are problematic for guide docs, so those have been given specific widths and associated heights. * docs(aio): use correct anchor for "back to the top" link The `#toc` anchor does not work when the page is wide enough that the TOC is floating to the side. * build(aio): add `#top-of-page` to path variants for link checking Since the `#top-of-page` is outside the rendered docs the `checkAnchorLinks` processor doesn't find them as valid targets for links. Adding them as a `pathVariant` solves this problem but will still catch links to docs that do not actually exist. * fix(aio): ensure that headings clear floated images * fix(aio): do not force live-example embedded image to 100% size This made them look too big, generally. Leaving them with no size means that they will look reasonable in large viewports and switch to 100% width in narrow viewports.
2017-05-09 23:53:32 +01:00
<img src="generated/images/guide/attribute-directives/highlight-directive-anim.gif" alt="Second Highlight">
</div>
{@a bindings}
## Passing values into an attribute directive
2017-04-01 01:57:13 +02:00
This section walks you through setting the highlight color while applying the `HighlightDirective`.
1. In `highlight.directive.ts`, import `Input` from `@angular/core`.
<code-example path="attribute-directives/src/app/highlight.directive.3.ts" header="src/app/highlight.directive.ts (imports)" region="imports"></code-example>
1. Add an `appHighlight` `@Input()` property.
<code-example path="attribute-directives/src/app/highlight.directive.3.ts" header="src/app/highlight.directive.ts" region="input"></code-example>
The `@Input()` decorator adds metadata to the class that makes the directive's `appHighlight` property available for binding.
2017-04-01 01:57:13 +02:00
1. In `app.component.ts`, add a `color` property to the `AppComponent`.
<code-example path="attribute-directives/src/app/app.component.1.ts" header="src/app/app.component.ts (class)" region="class"></code-example>
1. To simultaneously apply the directive and the color, use property binding with the `appHighlight` directive selector, setting it equal to `color`.
2017-04-01 01:57:13 +02:00
<code-example path="attribute-directives/src/app/app.component.html" header="src/app/app.component.html (color)" region="color"></code-example>
The `[appHighlight]` attribute binding performs two tasks:
* applies the highlighting directive to the `<p>` element
* sets the directive's highlight color with a property binding
2017-04-01 01:57:13 +02:00
### 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:
2017-04-01 01:57:13 +02:00
<code-example path="attribute-directives/src/app/app.component.html" header="src/app/app.component.html (v2)" region="v2"></code-example>
1. Revise the `AppComponent.color` so that it has no initial value.
<code-example path="attribute-directives/src/app/app.component.ts" header="src/app/app.component.ts (class)" region="class"></code-example>
1. Serve your application to verify that the user can choose the color with the radio buttons.
<div class="lightbox">
<img src="generated/images/guide/attribute-directives/highlight-directive-v2-anim.gif" alt="Animated gif of the refactored highlight directive changing color according to the radio button the user selects">
</div>
{@a second-property}
2017-04-01 01:57:13 +02:00
## 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`.
<code-example path="attribute-directives/src/app/highlight.directive.ts" header="src/app/highlight.directive.ts (defaultColor)" region="defaultColor"></code-example>
1. Revise the directive's `onMouseEnter` so that it first tries to highlight with the `highlightColor`, then with the `defaultColor`, and falls back to `red` if both properties are `undefined`.
<code-example path="attribute-directives/src/app/highlight.directive.ts" header="src/app/highlight.directive.ts (mouse-enter)" region="mouse-enter"></code-example>
2017-04-01 01:57:13 +02:00
1. 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 it is static.
<code-example path="attribute-directives/src/app/app.component.html" header="src/app/app.component.html (defaultColor)" region="defaultColor"></code-example>
As with components, you can add multiple directive property bindings to a host element.
2017-04-01 01:57:13 +02:00
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.
<div class="lightbox">
<img src="generated/images/guide/attribute-directives/highlight-directive-final-anim.gif" alt="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.">
</div>
{@a ngNonBindable}
## Deactivating Angular processing with `NgNonBindable`
To prevent expression evaluation in the browser, add `ngNonBindable` to the host element.
`ngNonBindable` deactivates interpolation, directives, and binding in templates.
In the following example, the expression `{{ 1 + 1 }}` renders just as it does in your code editor, and does not display `2`.
Merge remote-tracking branch 'en/master' into aio # Conflicts: # aio/content/cli/index.md # aio/content/guide/accessibility.md # aio/content/guide/ajs-quick-reference.md # aio/content/guide/angular-compiler-options.md # aio/content/guide/animations.md # aio/content/guide/aot-compiler.md # aio/content/guide/architecture-components.md # aio/content/guide/architecture-modules.md # aio/content/guide/architecture-next-steps.md # aio/content/guide/architecture-services.md # aio/content/guide/attribute-directives.md # aio/content/guide/bootstrapping.md # aio/content/guide/browser-support.md # aio/content/guide/cli-builder.md # aio/content/guide/comparing-observables.md # aio/content/guide/component-styles.md # aio/content/guide/creating-libraries.md # aio/content/guide/dependency-injection-in-action.md # aio/content/guide/dependency-injection-navtree.md # aio/content/guide/dependency-injection-providers.md # aio/content/guide/dependency-injection.md # aio/content/guide/deployment.md # aio/content/guide/deprecations.md # aio/content/guide/displaying-data.md # aio/content/guide/dynamic-component-loader.md # aio/content/guide/elements.md # aio/content/guide/file-structure.md # aio/content/guide/glossary.md # aio/content/guide/http.md # aio/content/guide/i18n.md # aio/content/guide/ivy-compatibility.md # aio/content/guide/language-service.md # aio/content/guide/lifecycle-hooks.md # aio/content/guide/module-types.md # aio/content/guide/ngmodule-faq.md # aio/content/guide/ngmodule-vs-jsmodule.md # aio/content/guide/ngmodules.md # aio/content/guide/observables-in-angular.md # aio/content/guide/pipes.md # aio/content/guide/providers.md # aio/content/guide/releases.md # aio/content/guide/route-animations.md # aio/content/guide/router-tutorial.md # aio/content/guide/router.md # aio/content/guide/rx-library.md # aio/content/guide/schematics-authoring.md # aio/content/guide/schematics-for-libraries.md # aio/content/guide/service-worker-config.md # aio/content/guide/service-worker-getting-started.md # aio/content/guide/structural-directives.md # aio/content/guide/styleguide.md # aio/content/guide/template-syntax.md # aio/content/guide/template-typecheck.md # aio/content/guide/testing.md # aio/content/guide/typescript-configuration.md # aio/content/guide/upgrade-setup.md # aio/content/guide/user-input.md # aio/content/guide/using-libraries.md # aio/content/guide/web-worker.md # aio/content/guide/workspace-config.md # aio/content/marketing/docs.md # aio/content/marketing/events.html # aio/content/navigation.json # aio/content/start/index.md # aio/content/start/start-data.md # aio/content/start/start-deployment.md # aio/content/tutorial/toh-pt2.md # aio/content/tutorial/toh-pt4.md # aio/package.json # aio/src/app/app.component.ts # aio/src/app/layout/footer/footer.component.html # aio/src/app/shared/custom-icon-registry.ts # aio/src/environments/environment.stable.ts # aio/tools/stackblitz-builder/builder.js # aio/tools/transforms/angular-content-package/index.js # aio/tools/transforms/templates/api/lib/memberHelpers.html # aio/yarn.lock # integration/ng_elements/e2e/app.e2e-spec.ts # integration/ng_elements/src/app.ts # packages/common/src/pipes/date_pipe.ts # packages/core/src/metadata/directives.ts # packages/core/src/metadata/ng_module.ts # packages/core/src/render/api.ts # packages/forms/src/directives/ng_model.ts # packages/forms/src/form_builder.ts # packages/forms/src/model.ts # packages/platform-browser/src/browser.ts # packages/router/src/config.ts # packages/router/src/directives/router_link.ts # packages/router/src/directives/router_link_active.ts # packages/router/src/events.ts # packages/router/src/router.ts # packages/router/src/router_module.ts # packages/router/src/router_state.ts
2020-11-28 12:50:51 +08:00
<code-example path="attribute-directives/src/app/app.component.html" linenums="false" header="src/app/app.component.html" region="ngNonBindable"></code-example>
Applying `ngNonBindable` to an element stops binding for that element's child elements.
However, `ngNonBindable` still allows directives to work on the element where you apply `ngNonBindable`.
In the following example, the `appHighlight` directive is still active but Angular does not evaluate the expression `{{ 1 + 1 }}`.
Merge remote-tracking branch 'en/master' into aio # Conflicts: # aio/content/cli/index.md # aio/content/guide/accessibility.md # aio/content/guide/ajs-quick-reference.md # aio/content/guide/angular-compiler-options.md # aio/content/guide/animations.md # aio/content/guide/aot-compiler.md # aio/content/guide/architecture-components.md # aio/content/guide/architecture-modules.md # aio/content/guide/architecture-next-steps.md # aio/content/guide/architecture-services.md # aio/content/guide/attribute-directives.md # aio/content/guide/bootstrapping.md # aio/content/guide/browser-support.md # aio/content/guide/cli-builder.md # aio/content/guide/comparing-observables.md # aio/content/guide/component-styles.md # aio/content/guide/creating-libraries.md # aio/content/guide/dependency-injection-in-action.md # aio/content/guide/dependency-injection-navtree.md # aio/content/guide/dependency-injection-providers.md # aio/content/guide/dependency-injection.md # aio/content/guide/deployment.md # aio/content/guide/deprecations.md # aio/content/guide/displaying-data.md # aio/content/guide/dynamic-component-loader.md # aio/content/guide/elements.md # aio/content/guide/file-structure.md # aio/content/guide/glossary.md # aio/content/guide/http.md # aio/content/guide/i18n.md # aio/content/guide/ivy-compatibility.md # aio/content/guide/language-service.md # aio/content/guide/lifecycle-hooks.md # aio/content/guide/module-types.md # aio/content/guide/ngmodule-faq.md # aio/content/guide/ngmodule-vs-jsmodule.md # aio/content/guide/ngmodules.md # aio/content/guide/observables-in-angular.md # aio/content/guide/pipes.md # aio/content/guide/providers.md # aio/content/guide/releases.md # aio/content/guide/route-animations.md # aio/content/guide/router-tutorial.md # aio/content/guide/router.md # aio/content/guide/rx-library.md # aio/content/guide/schematics-authoring.md # aio/content/guide/schematics-for-libraries.md # aio/content/guide/service-worker-config.md # aio/content/guide/service-worker-getting-started.md # aio/content/guide/structural-directives.md # aio/content/guide/styleguide.md # aio/content/guide/template-syntax.md # aio/content/guide/template-typecheck.md # aio/content/guide/testing.md # aio/content/guide/typescript-configuration.md # aio/content/guide/upgrade-setup.md # aio/content/guide/user-input.md # aio/content/guide/using-libraries.md # aio/content/guide/web-worker.md # aio/content/guide/workspace-config.md # aio/content/marketing/docs.md # aio/content/marketing/events.html # aio/content/navigation.json # aio/content/start/index.md # aio/content/start/start-data.md # aio/content/start/start-deployment.md # aio/content/tutorial/toh-pt2.md # aio/content/tutorial/toh-pt4.md # aio/package.json # aio/src/app/app.component.ts # aio/src/app/layout/footer/footer.component.html # aio/src/app/shared/custom-icon-registry.ts # aio/src/environments/environment.stable.ts # aio/tools/stackblitz-builder/builder.js # aio/tools/transforms/angular-content-package/index.js # aio/tools/transforms/templates/api/lib/memberHelpers.html # aio/yarn.lock # integration/ng_elements/e2e/app.e2e-spec.ts # integration/ng_elements/src/app.ts # packages/common/src/pipes/date_pipe.ts # packages/core/src/metadata/directives.ts # packages/core/src/metadata/ng_module.ts # packages/core/src/render/api.ts # packages/forms/src/directives/ng_model.ts # packages/forms/src/form_builder.ts # packages/forms/src/model.ts # packages/platform-browser/src/browser.ts # packages/router/src/config.ts # packages/router/src/directives/router_link.ts # packages/router/src/directives/router_link_active.ts # packages/router/src/events.ts # packages/router/src/router.ts # packages/router/src/router_module.ts # packages/router/src/router_state.ts
2020-11-28 12:50:51 +08:00
<code-example path="attribute-directives/src/app/app.component.html" linenums="false" header="src/app/app.component.html" region="ngNonBindable-with-directive"></code-example>
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.