Vinculando com Eventos de um Componente Filho em Angular
Outra forma de interação é o vínculo com eventos de um componente filho. Vamos definir o seguinte componente filho:
import { Component, EventEmitter, Output } from "@angular/core";
@Component({
selector: 'child-comp',
standalone: true,
template: `<button (click)="change(true)">+</button>
<button (click)="change(false)">-</button>`
})
export class ChildComponent {
@Output() onChanged = new EventEmitter<boolean>();
change(increased: boolean) {
this.onChanged.emit(increased);
}
}
Neste componente, o evento click
dos botões chama o método change
, que recebe um valor true
ou false
. Embora o evento possa ser tratado dentro do componente filho, quando precisamos transmiti-lo ao componente pai, usamos uma propriedade do tipo EventEmitter
, que, neste caso, é a propriedade onChanged
. Como o valor transmitido é true
ou false
, tipificamos essa propriedade como boolean
. A propriedade onChanged
deve ser de saída, por isso é decorada com o decorador @Output
.
Na prática, a propriedade onChanged
se torna um evento disparado no método change()
quando o botão é clicado, transmitindo-o para o componente pai.
Agora, definimos o código do componente pai:
import { Component } from "@angular/core";
import { ChildComponent } from "./child.component";
@Component({
selector: "my-app",
standalone: true,
imports: [ChildComponent],
template: `<h2>Quantidade de cliques: {{ clicks }}</h2>
<child-comp (onChanged)="onChanged($event)"></child-comp>`,
})
export class AppComponent {
clicks = 0;
onChanged(increased: boolean) {
increased ? this.clicks++ : this.clicks--;
}
}
Usando a expressão (onChanged)="onChanged($event)"
, vinculamos o método onChanged
ao evento onChanged()
disparado no componente filho. O parâmetro $event
encapsula todos os dados transmitidos pelo componente filho.
Assim, ao clicar nos botões do componente filho, o evento é transmitido ao componente pai, que aumenta ou diminui o contador conforme o valor recebido.
Vínculo Bidirecional
No exemplo anterior, vinculamos um evento do componente filho: quando o evento ocorre no componente filho, ele é tratado no componente pai por meio de um método. No entanto, também podemos usar o vínculo bidirecional entre as propriedades do componente pai e do componente filho. Por exemplo, considere o componente filho a seguir:
import { Component, Input, Output, EventEmitter } from "@angular/core";
import { FormsModule } from "@angular/forms";
@Component({
selector: "child-comp",
standalone: true,
imports: [FormsModule],
template: `<input [ngModel]="userName" (ngModelChange)="onNameChange($event)" />`,
})
export class ChildComponent {
@Input() userName: string = "";
@Output() userNameChange = new EventEmitter<string>();
onNameChange(model: string) {
this.userName = model;
this.userNameChange.emit(model);
}
}
Aqui, definimos a propriedade de entrada userName
, que está vinculada ao campo de texto input
. Usamos o atributo [ngModel]
para vincular o valor do campo de texto à propriedade userName
.
Para monitorar as mudanças no modelo deste campo, vinculamos o método onNameChange
ao atributo (ngModelChange
), que é acionado sempre que o valor muda. O ngModelChange
é, na verdade, um evento de mudança do valor inserido, portanto, temos aqui um vínculo com o evento.
Como o vínculo é unidirecional, o método de tratamento recebe o valor inserido, altera a propriedade userName
e gera o evento userNameChange
, que foi definido como um parâmetro de saída.
Assim, recebemos externamente um valor para a propriedade userName
e o definimos no campo de texto. Quando o usuário insere um valor no campo, disparamos externamente o evento userNameChange
.
Agora, definimos o código do componente pai:
import { Component } from "@angular/core";
import { ChildComponent } from "./child.component";
@Component({
selector: "my-app",
standalone: true,
imports: [ChildComponent],
template: `<child-comp [(userName)]="name"></child-comp>
<div>Nome selecionado: {{ name }}</div>`,
})
export class AppComponent {
name = "Tom";
}
Aqui, estabelecemos o vínculo bidirecional entre a propriedade userName
do componente filho
e a propriedade name
do componente pai. Não é necessário tratar manualmente o evento userNameChange
, pois tudo será feito automaticamente.