Two-way binding trong angular

0 phút đọc

Giới thiệu lại ngModel

Như chúng ta đã biết, ngModel được cung cấp là một directive ở trong NgModule có tên là FormsModule, vậy nên để sử dụng được nó chúng ta sẽ cần imports FormsModule vào NgModule quản lý component hiện tại. Hay nói cách khác, nếu component của bạn muốn sử dụng NgModel thì bạn phải imports FormsModule và NgModule quản lý component đó.

Ví dụ, chúng ta có AppComponent và nó được quản lý bởi AppModule, vậy nên chúng ta sẽ imports FormsModule vào AppModule như sau.

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 {}

Như thế là chúng ta có thể sử dụng được ngModel ở template, và sử dụng cú pháp vuông vuông tròn tròn [(ngModel)] để có được Two-way binding.

<!-- app.component.html -->
<p>Your name: {{ name }}</p>

<input type="text" [(ngModel)]="name" />
// app.component.ts
@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"],
})
export class AppComponent {
  name = "Tiep Phan";
}

Giờ đây mỗi lần bạn thay đổi giá trị của input thì thẻ p sẽ hiển thị tên được sync tương ứng.

Thực chất cách viết trên là viết tắt của property binding và event binding như sau:

<input type="text" [ngModel]="name" (ngModelChange)="name = $event" />

Vậy nên để tạo custom Two-way binding thì bạn chỉ cần tạo @Input và @Output với @Output có suffix là change là được, ví dụ valuevalueChange.

Toggle Component support Two-way binding

Chúng ta sẽ khởi tạo một component mới để minh họa, component có tên là toggle component:

ng g c toggle

Phần code của component sẽ được implement như sau:

// toggle.component.ts
import { Component, OnInit, Input, Output, EventEmitter } from "@angular/core";

@Component({
  selector: "app-toggle",
  templateUrl: "./toggle.component.html",
  styleUrls: ["./toggle.component.css"],
})
export class ToggleComponent implements OnInit {
  @Input() checked = false;
  @Output() checkedChange = new EventEmitter<boolean>();

  constructor() {}

  ngOnInit() {}

  toggle() {
    this.checked = !this.checked;
    this.checkedChange.emit(this.checked);
  }
}
<!-- toggle.component.html -->
<div
  class="toggle-wrapper"
  [class.checked]="checked"
  tabindex="0"
  (click)="toggle()"
>
  <div class="toggle"></div>
</div>
/* toggle.component.css */
.toggle-wrapper {
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: all 0.2s;
  width: 100px;
  height: 100px;
  border-radius: 50%;
  background-color: #fe4551;
  box-shadow: 0 20px 20px 0 rgba(#fe4551, 0.3);
}

.toggle-wrapper:active {
  width: 95px;
  height: 95px;
  box-shadow: 0 15px 15px 0 rgba(#fe4551, 0.5);
}
.toggle-wrapper .toggle {
  height: 17px;
  width: 17px;
}

.toggle {
  transition: all 0.2s ease-in-out;
  height: 20px;
  width: 20px;
  background-color: transparent;
  border: 10px solid #fff;
  border-radius: 50%;
  cursor: pointer;
  animation: red 0.7s linear forwards;
}

.toggle-wrapper.checked {
  background-color: #48e98a;
  box-shadow: 0 20px 20px 0 rgba(#48e98a, 0.3);
}

.toggle-wrapper.checked:active {
  box-shadow: 0 15px 15px 0 rgba(#48e98a, 0.5);
}

.toggle-wrapper.checked .toggle {
  width: 0;
  background-color: #fff;
  border-color: transparent;
  border-radius: 30px;
  animation: green 0.7s linear forwards !important;
}

Component trên của chúng ta không có quá khác biệt so với những component trước đây, nó đều sử dụng những concept cơ bản như @Input, @Output, class binding, style css.

Chỉ với việc sử dụng suffix change cho property checked chúng ta có thể sử dụng component này ở bất cứ đâu với cách dùng giống như ngModel:

<app-toggle [(checked)]="checked"></app-toggle>
Toggle

Lời kết

Như vậy trong bài này, chúng ta sẽ phải tìm hiểu cách để tạo ra custom Two-way binding bằng cách kết hợp giữa @Input và @Output. Ngoài ra chúng ta còn thực hành một số bài học trước đây như class binding. Hi vọng những bài viết dưới đây sẽ giúp ích cho các bạn tìm hiểu chi tiết hơn.

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào

Avatar TechMely Team
Được viết bởi

TechMely Team

Đôi khi, không cẩn thận biết một số chuyện, mới phát hiện ra rằng những điều bản thân để tâm lại nực cười đến thế.