Variáveis de Template e ViewChild - Angular
As variáveis de template permitem definir algumas variáveis dentro do template de um componente e, em seguida, referenciar essas variáveis dentro do mesmo template. Para definir essas variáveis, utiliza-se o símbolo de cerquilha (#). Por exemplo, vamos definir uma variável de template chamada userName
import { Component } from "@angular/core";
import { FormsModule } from "@angular/forms";
@Component({
selector: "my-app",
standalone: true,
imports: [FormsModule],
template: `
<p #userName>{{name}}</p>
<p>{{userName.textContent}}</p>
<input type="text" [(ngModel)]="name" />`
})
export class AppComponent {
name = "Tom";
}
A definição de template tem a seguinte estrutura:
<p #userName>{{name}}</p>
A definição da variável userName
<p>
<p>
userName.textContent
name
userName.textContent

Interação entre Componentes Pai e Filho
O uso de variáveis de template oferece uma maneira adicional de interação entre o componente pai e o componente filho. Por exemplo, vamos definir o seguinte componente filho ChildComponent
import { Component } from "@angular/core";
@Component({
selector: "child-comp",
standalone: true,
template: `<p>{{counter}}</p>`
})
export class ChildComponent {
counter = 0;
increment() { this.counter++; }
decrement() { this.counter--; }
}
Este componente define uma variável counter
increment
decrement
No código do componente principal, vamos incluir o componente filho:
import { Component } from "@angular/core";
import { ChildComponent } from "./child.component";
@Component({
selector: "my-app",
standalone: true,
imports: [ChildComponent],
template: `<child-comp #counter></child-comp>
<button (click)="counter.increment()">+</button>
<button (click)="counter.decrement()">-</button>`
})
export class AppComponent { }
Neste caso, a variável de template counter
<child-comp>
ChildComponent
ChildComponent
increment
decrement

ViewChild
Entretanto, as variáveis de template têm suas limitações: elas não podem ser usadas fora do template, nem mesmo no código da classe do componente. Por exemplo, não podemos escrever o seguinte:
import { Component } from "@angular/core";
import { ChildComponent } from "./child.component";
@Component({
selector: "my-app",
standalone: true,
imports: [ChildComponent],
template: `<child-comp #counter></child-comp>
<button (click)="increment()">+</button>
<button (click)="decrement()">-</button>`
})
export class AppComponent {
increment() { this.counter++; }
decrement() { this.counter--; }
}
Aqui, a propriedade this.counter
AppComponent
Para permitir o acesso a métodos e outras funcionalidades do componente filho, podemos utilizar o decorador ViewChild
ViewChild
import { Component, ViewChild } from "@angular/core";
import { ChildComponent } from "./child.component";
@Component({
selector: "my-app",
standalone: true,
imports: [ChildComponent],
template: `<child-comp></child-comp>
<button (click)="increment()">+</button>
<button (click)="decrement()">-</button>`
})
export class AppComponent {
@ViewChild(ChildComponent, { static: false })
private counterComponent: ChildComponent | undefined;
increment() { this.counterComponent?.increment(); }
decrement() { this.counterComponent?.decrement(); }
}
O primeiro parâmetro do decorador ViewChild
@Component
ChildComponent
static
Vinculando ViewChild a Variáveis de Template
Embora no exemplo anterior não tenhamos utilizado variáveis, é possível vincular uma propriedade a uma variável de template usando o decorador ViewChild
import { Component, ViewChild, ElementRef } from "@angular/core";
@Component({
selector: "my-app",
standalone: true,
imports: [],
template: `<p #nameText>{{name}}</p>
<p>{{nameText.textContent}}</p>
<button (click)="change()">Change</button>`
})
export class AppComponent {
@ViewChild("nameText", { static: false })
nameParagraph: ElementRef | undefined;
name = "Tom";
change() {
if (this.nameParagraph !== undefined) {
console.log(this.nameParagraph.nativeElement.textContent);
this.nameParagraph.nativeElement.textContent = "hello";
}
}
}
Aqui, no template, definimos a variável nameText
ViewChild
nameParagraph
nameText
nameParagraph
ElementRef | undefined
ElementRef
Ao clicar no botão, o conteúdo textual dessa variável é exibido no console e alterado.
ContentChild
Além do ViewChild
ContentChild
import { Component } from "@angular/core";
import { ChildComponent } from "./child.component";
@Component({
selector: "my-app",
standalone: true,
imports: [ChildComponent],
template: `<child-comp>
<h3 #headerContent>Welcome {{name}}!</h3>
</child-comp>`
})
export class AppComponent {
name = "Tom";
}
Aqui, definimos a variável #headerContent
<h3>
Como os dados do componente pai são passados diretamente para o componente filho, utilizaremos o elemento ng-content
import { Component, ContentChild, ElementRef } from "@angular/core";
@Component({
selector: "child-comp",
standalone: true,
template: `<ng-content></ng-content>
<button (click)="change()">Change</button>`
})
export class ChildComponent {
@ContentChild("headerContent", { static: false })
header: ElementRef | undefined;
change() {
if (this.header !== undefined) {
console.log(this.header);
this.header.nativeElement.textContent = "Hello to the world!";
}
}
}
Para acessar as variáveis passadas pelo ng-content
ContentChild
ElementRef | undefined