Simplifying Custom Two-Way Data Binding in Angular
Você sabe como lidar com a vinculação de dados bidirecional no Angular? Este guia de instruções mostrará como simplificar o processo. Leia mais agora.
Há três tipos de associações de dados no Angular, e elas são as seguintes:
- Interpolação
- Vinculação de evento
- Vinculação de propriedade
Se você está vindo de um histórico Angular 1.X, pode estar se perguntando onde está a vinculação de dados bidirecional. Lembre-se, a primeira vez que você viu a demonstração do AngularJS 1.X e ficou impressionado com o poder do ng-model? Sim, como você, também fiquei muito impressionado com o poder da vinculação de dados bidirecional no AngularJS 1. Mesmo assim, a vinculação de dados bidirecional do AngularJS 1 foi linda, ela veio com a bagagem do ciclo de resumo e $watch.
Para simplificar as coisas, Angular não possui nenhuma ligação de dados bidirecional interna. Isso não significa; Você não pode ter associação de dados bidirecional em Angular aplicativo. Vamos lá, não podemos pensar em criar um aplicativo da Web moderno sem ter o poder da vinculação de dados bidirecional. Então, neste post, vamos aprender como trabalhar com vinculação de dados bidirecional no Angular
Two-way data binding with ngModel
Angular nos fornece uma diretiva ngModel para obter a ligação de dados bidirecional. É muito simples e direto usar a diretiva ngModel, conforme mostrado na lista abaixo:
import {Component} from '@angular/core';
@Component({
moduleId:module.id,
selector:'my-app',
template:`
<div class="container">
<input [(ngModel)]='name' />
<br/>
<h1>Hello {{name}}</h1>
</div>
`
})
export class AppComponent{
}
Para usar a diretiva ngModel, precisamos importar FormsModule no aplicativo. Para sua referência, abaixo estou listando app.module.ts que está importando FormsModule além de outros módulos necessários.
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
@NgModule({
imports: [ BrowserModule,FormsModule ],
declarations: [ AppComponent],
bootstrap: [ AppComponent ]
})
export class AppModule { }
Na demonstração acima, ao digitar no elemento de entrada, o valor da entrada será atribuído à variável name e também será exibido de volta para a visualização. Portanto, estamos implementando a vinculação de dados bidirecional usando ngModel, conforme mostrado na imagem abaixo:

Ligação de dados bidirecional sem ngModel
Para entender o funcionamento da diretiva ngModel, vamos ver como podemos obter a ligação de dados bidirecional sem usar a diretiva ngModel. Para fazer isso, precisamos usar
- Associação de propriedade para vincular a expressão à propriedade de valor do elemento de entrada. Nesta demonstração, estamos vinculando a expressão da variável name à propriedade value.
- Associação de eventos para emitir eventos de entrada no elemento de entrada. Sim, há um evento de entrada que será acionado sempre que o usuário inserir no elemento de entrada. Usando a associação de eventos, o evento de entrada seria associado a uma expressão.
Portanto, usando a associação de propriedade e a associação de eventos, a associação de dados bidirecional pode ser obtida conforme mostrado na listagem abaixo:
import {Component} from '@angular/core';
@Component({
moduleId:module.id,
selector:'my-app',
template:`
<div class="container">
<input [value]="name" (input)="name=$event.target.value" />
<br/>
<h1>Hello {{name}}</h1>
</div>
`
})
export class AppComponent{
name : string = "";
}
Da mesma forma que a demonstração da diretiva ngModel nesta demonstração também, ao digitar no elemento de entrada, o valor do elemento de entrada será atribuído à variável name e também será exibido de volta para a visualização.
Portanto, estamos implementando a vinculação de dados bidirecional sem usar ngModel usando o código mostrado na imagem abaixo:

Vamos entender algumas coisas importantes aqui:
- [value]="name" é a associação de propriedade. Estamos vinculando a propriedade de valor do elemento de entrada com o nome da variável (ou expressão).
- (input)= "expression" é a vinculação de eventos. Sempre que o evento de entrada for disparado, a expressão será executada.
- "name=$event.target.value" é uma expressão que atribui o valor inserido à variável name.
- Name pode ser acessada dentro da classe AppComponent.
Até agora, vimos a ligação de dados bidirecional usando ngModel e sem ngModel. Podemos concluir que a diretiva ngModel nada mais é do que uma combinação de associação de propriedade e associação de evento. A associação de eventos é indicada usando colchetes pequenos e a associação de propriedade é indicada usando colchetes quadrados [], e se você notar que a sintaxe de ngModel é [(ngModel)], que é como uma banana colocada em uma caixa sugere que é uma combinação de associação de evento e propriedade.
Custom two-way data binding
Devemos ter muito cuidado ao criar uma ligação de dados bidirecional personalizada ou confiar na diretiva ngModel. Nós realmente não precisamos criar uma ligação de dados bidirecional personalizada sempre. No entanto, é bom conhecer as etapas para criar uma associação de dados bidirecional personalizada. Vamos criar um componente customcounter com a vinculação de dados bidirecional habilitada. Vamos seguir os passos:
Step 1
Crie um componente com dois botões e métodos para incrementar e diminuir.
@Component({
moduleId: module.id,
selector:'countercomponent',
template:`
<button (click)='increnent()'>Increment</button>
{{count}}
<button (click)='decrement()'>Decrement</button>
`
})
export class AppChildComponent {
count : number = 0;
increment(){
this.count = this.count+1;
}
decrement(){
this.count = this.count - 1;
}
}
Acima, criamos um componente muito simples para incrementar e diminuir a contagem. Agora, podemos usar esse componente dentro de outro componente, no entanto, a vinculação de dados bidirecional não está habilitada nesse componente. Para habilitar isso, precisamos usar @Input e @Output propriedades.
Step 2
Vamos criar um getter com a propriedade @Input(). Este getter retornará a contagem. Como ele é atribuído ao decorador @Input(), o consumidor desse componente pode vincular esse valor usando a associação de propriedade.
@Input()
get counter(){
return this.count;
}
Step 3
Para criar uma associação de dados bidirecional, precisamos criar um evento do tipo EventEmitter. Esse evento é atribuído ao decorador @Output() de modo que possa ser emitido para o componente do consumidor. Estamos criando um objeto de evento no construtor do componente.
@Output() counterChange : EventEmitter<number>;
constructor(){
this.counterChange = new EventEmitter();
}
Step 4
Como última etapa, as funções de incremento e decremento devem emitir o evento counterChange. Portanto, precisamos modificar a função de incremento e decremento, conforme mostrado na lista abaixo:
increment() {
this.count=this.count+1;
this.counterChange.emit(this.count);
}
decrement() {
this.count=this.count - 1;
this.counterChange.emit(this.count);
}
Ambas as funções estão emitindo o evento counterChange. Juntando todas as peças, um componente com vinculação de dados bidirecional personalizada será semelhante ao código listado abaixo:
import {Component,Input,Output,EventEmitter} from '@angular/core';
@Component({
moduleId: module.id,
selector:'countercomponent',
template:`
<button (click)='increment()'>Increment</button>
{{count}}
<button (click)='decrement()'>Decrement</button>
`
})
export class AppChildComponent {
count : number = 0;
@Output() counterChange : EventEmitter<number>;
constructor(){
this.counterChange = new EventEmitter();
}
@Input()
get counter(){
return this.count;
}
increment(){
this.count = this.count+1;
this.counterChange.emit(this.count);
}
decrement(){
this.count = this.count - 1;
this.counterChange.emit(this.count);
}
}
Step 5
Como qualquer componente simples, um componente com ligação de dados bidirecional pode ser usado dentro de outro componente.
import {Component} from '@angular/core';
@Component({
moduleId:module.id,
selector:'my-app',
template:`
<div class="container">
<br/>
<countercomponent [(counter)]="c"></countercomponent>
<br/>
<h2>count = {{c}}</h2>
</div>
`
})
export class AppComponent {
c : number = 1;
}
A principal coisa que você pode querer observar é a maneira como o valor de uma propriedade de contador é definido dentro de AppComponent. Como a diretiva ngModel, a propriedade counter também é definida usando a sintaxe banana in box [(counter)]
Conclusão
A associação de dados bidirecional no Angular é suportada pela associação de eventos e propriedades. Não há associação de dados bidirecional embutida. Podemos usar a diretiva ngModel para usar a ligação de dados bidirecional. Além disso, se necessário, associações de dados bidirecionais personalizadas podem ser criadas. A associação de dados bidirecional personalizada é útil em controles de formulário.
Nesta postagem, aprendemos sobre ngModel e criação de vinculação de dados bidirecional personalizada. Espero que você ache este post útil. Obrigado por ler.