Thử Nghiệm Với Angular 2 Phần 9: Angular 2 Two-way Binding Và Tạo Custom Two-way Data Binding


Angular 2 Two-way Binding Và Tạo Custom Two-way Data Binding

Angular 2 Component có thể truyền vào data với @Input hoặc gửi event ra ngoài với @Output, chúng đều là unidirectional data flow hay one-way binding. Angular 2 Two-way Binding không là built-in trong Angular 2. Tuy vậy chúng ta vẫn có thể áp dụng Two-way Binding bằng cách sử dụng directive ngModel trong Angular 2. Bài học này chúng ta sẽ cùng tìm hiểu về Two-way Binding và cách tạo Custom Two-way Data Binding trong Angular 2.

Giới thiệu về Angular 2 Two-way Binding với ngModel

Angular 2 có một directive để áp dụng two-way binding đó là ngModel. Chúng ta có thể bao ngModel trong cặp dấu [()], nó sẽ thực hiện đồng bộ dữ liệu từ Component vs DOM và ngược lại.

app.component.html

<div>
  <input type="text" 
    (keyup.enter)="updateMesssages()" 
    [(ngModel)]="message"
  >
  <button (click)="updateMesssages()">Button...</button>
</div>

app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  messages: string[] = [];
  message: string = '';
  updateMesssages() {
    this.messages.push(this.message);
    this.message = '';
  }
}

Nếu không sử dụng [(ngModel)] chúng ta có thể hoàn toàn viết một cú pháp tương ứng cho ví dụ trên như sau:

app.component.html

<div>
  <input type="text" 
    (keyup.enter)="updateMesssages()" 
    [value]="message" 
    (input)="message = $event.target.value"
  >
  <button (click)="updateMesssages()">Button...</button>
</div>

Khi không sử dụng directive ngModel ở cấu trúc binding bởi cặp dấu [()], chúng ta hoàn toàn có thể tách thành 2 cấu trúc binding riêng biệt là event binding và property binding:

app.component.html

<div>
  <input type="text" 
    (keyup.enter)="updateMesssages()" 
    [ngModel]="message" 
    (ngModelChange)="message = $event">
  <button (click)="updateMesssages()">Button...</button>
</div

Như các bạn có thể thấy,  directive ngModel ở ví dụ minh họa trên bao gồm property ngModel và event ngModelChange.

## Tạo Custom Two-way Data Binding

Để tạo được Custom Two-way Data Binding, chúng ta kết hợp @Input (property binding) và @Output (event binding) với cú pháp:

Tên của input là xyz thì tên của output là xyzChange.

switches.component.ts

import { 
  Component, 
  OnInit, 
  Input, 
  Output, 
  EventEmitter 
} from '@angular/core';

@Component({
  selector: 'tp-switches',
  templateUrl: './switches.component.html',
  styleUrls: ['./switches.component.scss']
})
export class SwitchesComponent implements OnInit {
  @Input() checked: Boolean = false;                              // input
  @Output('checkedChange') change = new EventEmitter<boolean>();  // output

  constructor() { }

  ngOnInit() {
  }
  emitChangeValue(event) {
    this.change.emit(event.target.checked);
  }
}

Sử dụng trong một component khác:

contact-list.component.html

<div>
  <tp-switches [(checked)]="contact.avatar.round">
  </tp-switches>
  <tp-contact-image-detail
    [avatar-url]="contact.avatar?.url"
    [round]="contact.avatar?.round"
  >
  </tp-contact-image-detail>
</div>

Lưu ý: two-way binding không dùng kết hợp với dạng check null như contact.avatar?.round .

Video bài học

Tham khảo

Documentation:  https://angular.io/docs/ts/latest/guide/architecture.html#!#data-binding

Code demo: https://github.com/tieppt/try-angular/tree/lesson-9

Back to blog