Mude a aparência ou comportamento de elementos DOM e components Angular com attribute directives.
Construindo uma attribute directive
Esta seção orienta você na criação de uma directive de destaque que define a cor de fundo do elemento host para amarelo.
Para criar uma directive, use o comando CLI
ng generate directive.ng generate directive highlightO CLI cria
src/app/highlight.directive.ts, um arquivo de teste correspondentesrc/app/highlight.directive.spec.ts.src/app/highlight.directive.ts
import {Directive} from '@angular/core';@Directive({ selector: '[appHighlight]',})export class HighlightDirective {}A propriedade de configuração do decorator
@Directive()especifica o seletor de atributo CSS da directive,[appHighlight].Importe
ElementRefde@angular/core.ElementRefconcede acesso direto ao elemento DOM host através de sua propriedadenativeElement.Adicione
ElementRefnoconstructor()da directive para injetar uma referência ao elemento DOM host, o elemento ao qual você aplicaappHighlight.Adicione lógica à classe
HighlightDirectiveque define o fundo como amarelo.
src/app/highlight.directive.ts
import {Directive, ElementRef, inject} from '@angular/core';@Directive({ selector: '[appHighlight]',})export class HighlightDirective { private el = inject(ElementRef); constructor() { this.el.nativeElement.style.backgroundColor = 'yellow'; }}
ÚTIL: Directives não suportam namespaces.
src/app/app.component.avoid.html (não suportado)
<p app:Highlight>This is invalid</p>
Aplicando uma attribute directive
- Para usar a
HighlightDirective, adicione um elemento<p>ao template HTML com a directive como um atributo.
src/app/app.component.html
<h1>My First Attribute Directive</h1><p appHighlight>Highlight me!</p><p appHighlight="yellow">Highlighted in yellow</p><p [appHighlight]="'orange'">Highlighted in orange</p><p [appHighlight]="color">Highlighted with parent component's color</p>
O Angular cria uma instância da classe HighlightDirective e injeta uma referência ao elemento <p> no constructor da directive, que define o estilo de fundo do elemento <p> como amarelo.
Manipulando eventos do usuário
Esta seção mostra como detectar quando um usuário passa o mouse sobre o elemento ou sai dele e responder definindo ou limpando a cor de destaque.
- Importe
HostListenerde '@angular/core'.
src/app/highlight.directive.ts (imports)
import {Directive, ElementRef, HostListener, inject} from '@angular/core';@Directive({ selector: '[appHighlight]',})export class HighlightDirective { private el = inject(ElementRef); @HostListener('mouseenter') onMouseEnter() { this.highlight('yellow'); } @HostListener('mouseleave') onMouseLeave() { this.highlight(''); } private highlight(color: string) { this.el.nativeElement.style.backgroundColor = color; }}
- Adicione dois event handlers que respondem quando o mouse entra ou sai, cada um com o decorator
@HostListener().
src/app/highlight.directive.ts (mouse-methods)
import {Directive, ElementRef, HostListener, inject} from '@angular/core';@Directive({ selector: '[appHighlight]',})export class HighlightDirective { private el = inject(ElementRef); @HostListener('mouseenter') onMouseEnter() { this.highlight('yellow'); } @HostListener('mouseleave') onMouseLeave() { this.highlight(''); } private highlight(color: string) { this.el.nativeElement.style.backgroundColor = color; }}
Inscreva-se em eventos do elemento DOM que hospeda uma attribute directive, o <p> neste caso, com o decorator @HostListener().
ÚTIL: Os handlers delegam para um método auxiliar, highlight(), que define a cor no elemento DOM host, el.
A directive completa é a seguinte:
src/app/highlight.directive.ts
import {Directive, ElementRef, HostListener, inject} from '@angular/core';@Directive({ selector: '[appHighlight]',})export class HighlightDirective { private el = inject(ElementRef); @HostListener('mouseenter') onMouseEnter() { this.highlight('yellow'); } @HostListener('mouseleave') onMouseLeave() { this.highlight(''); } private highlight(color: string) { this.el.nativeElement.style.backgroundColor = color; }}
A cor de fundo aparece quando o ponteiro passa sobre o elemento de parágrafo e desaparece quando o ponteiro se move para fora.
Passando valores para uma attribute directive
Esta seção orienta você a definir a cor de destaque ao aplicar a HighlightDirective.
- Em
highlight.directive.ts, importeInputde@angular/core.
src/app/highlight.directive.ts (imports)
import {Directive, ElementRef, HostListener, inject, input} from '@angular/core';@Directive({ selector: '[appHighlight]',})export class HighlightDirective { private el = inject(ElementRef); appHighlight = input(''); @HostListener('mouseenter') onMouseEnter() { this.highlight(this.appHighlight() || 'red'); } @HostListener('mouseleave') onMouseLeave() { this.highlight(''); } private highlight(color: string) { this.el.nativeElement.style.backgroundColor = color; }}
Adicione uma propriedade
inputappHighlight.src/app/highlight.directive.ts
import {Directive, ElementRef, HostListener, inject, input} from '@angular/core';@Directive({ selector: '[appHighlight]',})export class HighlightDirective { private el = inject(ElementRef); appHighlight = input(''); @HostListener('mouseenter') onMouseEnter() { this.highlight(this.appHighlight() || 'red'); } @HostListener('mouseleave') onMouseLeave() { this.highlight(''); } private highlight(color: string) { this.el.nativeElement.style.backgroundColor = color; }}A função
input()adiciona metadados à classe que torna a propriedadeappHighlightda directive disponível para binding.Em
app.component.ts, adicione uma propriedadecoloraoAppComponent.
src/app/app.component.ts (class)
import {Component} from '@angular/core';import {HighlightDirective} from './highlight.directive';@Component({ selector: 'app-root', templateUrl: './app.component.1.html', imports: [HighlightDirective],})export class AppComponent { color = 'yellow';}
Para aplicar simultaneamente a directive e a cor, use property binding com o seletor da directive
appHighlight, definindo-o igual acolor.src/app/app.component.html (color)
<h1>My First Attribute Directive</h1><h2>Pick a highlight color</h2><div> <input type="radio" name="colors" (click)="color='lightgreen'">Green <input type="radio" name="colors" (click)="color='yellow'">Yellow <input type="radio" name="colors" (click)="color='cyan'">Cyan</div><p [appHighlight]="color">Highlight me!</p><p [appHighlight]="color" defaultColor="violet"> Highlight me too!</p><hr><h2>Mouse over the following lines to see fixed highlights</h2><p [appHighlight]="'yellow'">Highlighted in yellow</p><p appHighlight="orange">Highlighted in orange</p><hr><h2>ngNonBindable</h2><p>Use ngNonBindable to stop evaluation.</p><p ngNonBindable>This should not evaluate: {{ 1 + 1 }}</p><h3>ngNonBindable with a directive</h3><div ngNonBindable [appHighlight]="'yellow'">This should not evaluate: {{ 1 +1 }}, but will highlight yellow.</div>O attribute binding
[appHighlight]executa duas tarefas:- Aplica a directive de destaque ao elemento
<p> - Define a cor de destaque da directive com um property binding
- Aplica a directive de destaque ao elemento
Definindo o valor com entrada do usuário
Esta seção orienta você a adicionar botões de opção para vincular sua escolha de cor à directive appHighlight.
- Adicione marcação a
app.component.htmlpara escolher uma cor da seguinte forma:
src/app/app.component.html (v2)
<h1>My First Attribute Directive</h1><h2>Pick a highlight color</h2><div> <input type="radio" name="colors" (click)="color='lightgreen'">Green <input type="radio" name="colors" (click)="color='yellow'">Yellow <input type="radio" name="colors" (click)="color='cyan'">Cyan</div><p [appHighlight]="color">Highlight me!</p><p [appHighlight]="color" defaultColor="violet"> Highlight me too!</p><hr><h2>Mouse over the following lines to see fixed highlights</h2><p [appHighlight]="'yellow'">Highlighted in yellow</p><p appHighlight="orange">Highlighted in orange</p><hr><h2>ngNonBindable</h2><p>Use ngNonBindable to stop evaluation.</p><p ngNonBindable>This should not evaluate: {{ 1 + 1 }}</p><h3>ngNonBindable with a directive</h3><div ngNonBindable [appHighlight]="'yellow'">This should not evaluate: {{ 1 +1 }}, but will highlight yellow.</div>
- Revise o
AppComponent.colorpara que ele não tenha valor inicial.
src/app/app.component.ts (class)
import {Component} from '@angular/core';import {HighlightDirective} from './highlight.directive';@Component({ selector: 'app-root', templateUrl: './app.component.html', imports: [HighlightDirective],})export class AppComponent { color = '';}
- Em
highlight.directive.ts, revise o métodoonMouseEnterpara que ele primeiro tente destacar comappHighlighte volte pararedseappHighlightforundefined.
src/app/highlight.directive.ts (mouse-enter)
import {Directive, ElementRef, HostListener, inject, input} from '@angular/core';@Directive({ selector: '[appHighlight]',})export class HighlightDirective { private el = inject(ElementRef); appHighlight = input(''); @HostListener('mouseenter') onMouseEnter() { this.highlight(this.appHighlight() || 'red'); } @HostListener('mouseleave') onMouseLeave() { this.highlight(''); } private highlight(color: string) { this.el.nativeElement.style.backgroundColor = color; }}
- Sirva sua aplicação para verificar que o usuário pode escolher a cor com os botões de opção.
Binding para uma segunda propriedade
Esta seção orienta você a configurar sua aplicação para que o desenvolvedor possa definir a cor padrão.
- Adicione uma segunda propriedade
Input()àHighlightDirectivechamadadefaultColor.
src/app/highlight.directive.ts (defaultColor)
import {Directive, ElementRef, HostListener, inject, input} from '@angular/core';@Directive({ selector: '[appHighlight]',})export class HighlightDirective { private el = inject(ElementRef); defaultColor = input(''); appHighlight = input(''); @HostListener('mouseenter') onMouseEnter() { this.highlight(this.appHighlight() || this.defaultColor() || 'red'); } @HostListener('mouseleave') onMouseLeave() { this.highlight(''); } private highlight(color: string) { this.el.nativeElement.style.backgroundColor = color; }}
- Revise o
onMouseEnterda directive para que ele primeiro tente destacar com oappHighlight, depois com odefaultColor, e volte pararedse ambas as propriedades foremundefined.
src/app/highlight.directive.ts (mouse-enter)
import {Directive, ElementRef, HostListener, inject, input} from '@angular/core';@Directive({ selector: '[appHighlight]',})export class HighlightDirective { private el = inject(ElementRef); defaultColor = input(''); appHighlight = input(''); @HostListener('mouseenter') onMouseEnter() { this.highlight(this.appHighlight() || this.defaultColor() || 'red'); } @HostListener('mouseleave') onMouseLeave() { this.highlight(''); } private highlight(color: string) { this.el.nativeElement.style.backgroundColor = color; }}
Para fazer binding com
AppComponent.colore voltar para "violet" como a cor padrão, adicione o seguinte HTML. Neste caso, o bindingdefaultColornão usa colchetes,[], porque é estático.src/app/app.component.html (defaultColor)
<h1>My First Attribute Directive</h1><h2>Pick a highlight color</h2><div> <input type="radio" name="colors" (click)="color='lightgreen'">Green <input type="radio" name="colors" (click)="color='yellow'">Yellow <input type="radio" name="colors" (click)="color='cyan'">Cyan</div><p [appHighlight]="color">Highlight me!</p><p [appHighlight]="color" defaultColor="violet"> Highlight me too!</p><hr><h2>Mouse over the following lines to see fixed highlights</h2><p [appHighlight]="'yellow'">Highlighted in yellow</p><p appHighlight="orange">Highlighted in orange</p><hr><h2>ngNonBindable</h2><p>Use ngNonBindable to stop evaluation.</p><p ngNonBindable>This should not evaluate: {{ 1 + 1 }}</p><h3>ngNonBindable with a directive</h3><div ngNonBindable [appHighlight]="'yellow'">This should not evaluate: {{ 1 +1 }}, but will highlight yellow.</div>Assim como com components, você pode adicionar múltiplos property bindings de directive a um elemento host.
A cor padrão é vermelho se não houver binding de cor padrão. Quando o usuário escolhe uma cor, a cor selecionada se torna a cor de destaque ativa.
Desativando o processamento do Angular com NgNonBindable
Para prevenir a avaliação de expressões no navegador, adicione ngNonBindable ao elemento host.
ngNonBindable desativa interpolation, directives e binding em templates.
No exemplo a seguir, a expressão {{ 1 + 1 }} renderiza exatamente como aparece no seu editor de código, e não exibe 2.
src/app/app.component.html
<h1>My First Attribute Directive</h1><h2>Pick a highlight color</h2><div> <input type="radio" name="colors" (click)="color='lightgreen'">Green <input type="radio" name="colors" (click)="color='yellow'">Yellow <input type="radio" name="colors" (click)="color='cyan'">Cyan</div><p [appHighlight]="color">Highlight me!</p><p [appHighlight]="color" defaultColor="violet"> Highlight me too!</p><hr><h2>Mouse over the following lines to see fixed highlights</h2><p [appHighlight]="'yellow'">Highlighted in yellow</p><p appHighlight="orange">Highlighted in orange</p><hr><h2>ngNonBindable</h2><p>Use ngNonBindable to stop evaluation.</p><p ngNonBindable>This should not evaluate: {{ 1 + 1 }}</p><h3>ngNonBindable with a directive</h3><div ngNonBindable [appHighlight]="'yellow'">This should not evaluate: {{ 1 +1 }}, but will highlight yellow.</div>
Aplicar ngNonBindable a um elemento interrompe o binding para os elementos filhos desse elemento.
No entanto, ngNonBindable ainda permite que directives funcionem no elemento onde você aplica ngNonBindable.
No exemplo a seguir, a directive appHighlight ainda está ativa, mas o Angular não avalia a expressão {{ 1 + 1 }}.
src/app/app.component.html
<h1>My First Attribute Directive</h1><h2>Pick a highlight color</h2><div> <input type="radio" name="colors" (click)="color='lightgreen'">Green <input type="radio" name="colors" (click)="color='yellow'">Yellow <input type="radio" name="colors" (click)="color='cyan'">Cyan</div><p [appHighlight]="color">Highlight me!</p><p [appHighlight]="color" defaultColor="violet"> Highlight me too!</p><hr><h2>Mouse over the following lines to see fixed highlights</h2><p [appHighlight]="'yellow'">Highlighted in yellow</p><p appHighlight="orange">Highlighted in orange</p><hr><h2>ngNonBindable</h2><p>Use ngNonBindable to stop evaluation.</p><p ngNonBindable>This should not evaluate: {{ 1 + 1 }}</p><h3>ngNonBindable with a directive</h3><div ngNonBindable [appHighlight]="'yellow'">This should not evaluate: {{ 1 +1 }}, but will highlight yellow.</div>
Se você aplicar ngNonBindable a um elemento pai, o Angular desativa interpolation e binding de qualquer tipo, como property binding ou event binding, para os filhos do elemento.