Directive Duplications

Because we no longer define every component and directive directly in every component that needs it, we need to be aware of how Angular modules handle directives and components that target the same element (have the same selector).

Let's assume for a moment that by mistake, we have created two directives that target the same property:

This example is a variation of the code found in the official documentation.

blue-highlight.directive.ts

  1. import { Directive, ElementRef, Renderer } from '@angular/core';
  2. @Directive({
  3. selector: '[appHighlight]'
  4. })
  5. export class BlueHighlightDirective {
  6. constructor(renderer: Renderer, el: ElementRef) {
  7. renderer.setElementStyle(el.nativeElement, 'backgroundColor', 'blue');
  8. renderer.setElementStyle(el.nativeElement, 'color', 'gray');
  9. }
  10. }

yellow-highlight.directive.ts

  1. import { Directive, ElementRef, Renderer } from '@angular/core';
  2. @Directive({
  3. selector: '[appHighlight]'
  4. })
  5. export class YellowHighlightDirective {
  6. constructor(renderer: Renderer, el: ElementRef) {
  7. renderer.setElementStyle(el.nativeElement, 'backgroundColor', 'yellow');
  8. }
  9. }

These two directives are similar, they are trying to style an element. The BlueHighlightDirective will try to set the background color of the element to blue while changing the color of the text to gray, while the YellowHighlightDirective will try only to change the background color to yellow. Notice that both are targeting any HTML element that has the property appHighlight. What would happen if we add both directives to the same module?

app.module.ts

  1. // Imports
  2. @NgModule({
  3. imports: [BrowserModule],
  4. declarations: [
  5. AppComponent,
  6. BlueHighlightDirective,
  7. YellowHighlightDirective
  8. ],
  9. bootstrap: [AppComponent]
  10. })
  11. export class AppModule { }

Let's see how we would use it in the only component of the module.

app.component.ts

  1. import { Component } from '@angular/core';
  2. @Component({
  3. selector: 'app-root',
  4. template: '<h1 appHighlight>My Angular App</h1>'
  5. })
  6. export class AppComponent {}

We can see that in the template of our component, we are using the directive appHighlight in our h1 element but, which styles are going to end up being applied?

The answer is: the text is going to be gray and the background yellow.

View Example

We are allowed to define multiple directives that target the same elements in the same module. What's going to happen is that Angular is going to do every transformation in order.

  1. declarations: [
  2. ...,
  3. BlueHighlightDirective,
  4. YellowHighlightDirective
  5. ]

Because we have defined both directives in an array, and arrays are ordered collection of items, when the compiler finds an element with the property appHighlight, it will first apply the transformations of BlueHighlightDirective, setting the text gray and the background blue, and then will apply the transformations of YellowHighlightDirective, changing again the background color to yellow.

In summary, when two or more directives target the same element, they are going to be applied in the order they were defined.

原文: https://angular-2-training-book.rangle.io/handout/modules/directive-duplications.html