Data Binding trong AngularJS và các Directive dùng trong Data Biniding

Trong bài viết trước mình đã nhắc đến Directive và Custom Directive. Vì vậy 1 phần nào đó chúng ta đều hiểu được Directive là 1 trong những tính năng mạnh mẽ nhất của AngularJS. Vậy mình sẽ vào phần chính luôn đó là Data binding Directive.

Data Binding Directive

Trong Data Binding giúp thể hiện giá trị của DOM. mà điều thú vị ở đây là kết quả mà data bạn cập nhật sẽ hiển thị ngay chứ không cần phải reload page tức là cách thức tự đồng bộ hóa (synchronization) dữ liệu giữa model và view trong angularJS, nó cho phép bạn tạo sự liên kết ràng buộc giữa model và template thông qua angularJS. Data Bindind bao gồm nhưng directive sau:

  • ng-bind
  • ng-bind-html
  • ng-bind-template
  • ng-model
  • ng-non-bindable

Sau đây mình sẽ đi cụ thể vào từng directive và sẽ kết hợp giải thích Data Binding

1. Ng-bind

Ng-bind được biên dịch ở cấp đầu tiên của ứng dụng nghĩa là cấp độ 0. Trong 1 thẻ HTML có sử dụng ng-bind thì AngularJS sẽ tìm và thay thế nội dụng trong thẻ HTML bằng với giá trị mà có cùng tên định nghĩ trong ng-bind.

Trong thực tế không nên sử dụng ng-bind 1 các trực tiếp (VD: <div ng-bind="result"></div>) vì đôi khi sẽ gây ra các lỗi phát sinh không cho phép nội dung trong HTML được cập nhật. Thay vào đó chúng ta nên sử dụng standard class attributes (<div class="ng-bind : result"></div>) Lúc này giá trị của class attributes là tên của directive.

VD: Sử dụng ng-bind

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Example ng-bind</title>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js"></script>
  </head>
  <body ng-app="">
      <input ng-model="result" />
      <div class="ng-bind: result"></div>
      #<div ng-bind="result">
  </body>
</html>

Tuy nhiên chúng ta có thể dùng quy tắc mở 2 cặp ngoặc nhọn {{result}}

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Example ng-bind</title>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js"></script>
  </head>
  <body ng-app="">
      <input ng-model="result" />
      {{result}}
  </body>
</html>

Kết luận: Chúng ta nên sử dụng ng-bind trong trường hợp liên kết dữ liệu với ng-model và muốn quản lý quá trình lưu model vào $scope. còn không chúng ta sử dụng {{}} sẽ tốt hơn.

Vậy tại sao khi ta sử dụng ng-bind và {{}} thì mỗi giá trị trong model khi phải nhập dữ liệu như các thẻ input, textarea, selectbox thay đổi thì lập tức phân tử trong HTML sẽ thay đổi theo. Đó là do kiểu data binding two-way binding khi gọi ng-bind hoặc khi nào gặp {{}} thì AngularJS sẽ tạo ra 1 two-way binding nhằm lấy giá trị từ các thẻ nhập chèn vào 1 phần tử HTML.

Vậy cách thức hoạt động của Data binding trong Angular là gì?

Mình sẽ giải thích 3 cách thức hoạt động của Data binding :

one way binding, two way binding, one time binding

  • One way binding:

One_Way_Data_Binding.png

Scope trong Controller sẽ truyền dữ liệu tời view. Lúc này :

Scope Data : sẽ được truyền tới View và nếu Scope Data thay đổi thì nó sẽ lập tức truyền tới View và Data View sẽ thay đổi theo.

Data View: Scope Data sẽ không thay đổi với bất kỳ sự thay đổi dữ liệu nào trong data view

Điều này được AngulerJS như 1 "dữ liệu chân lý duy nhất" (single-source-of-truth) và nó thường được sử dụng với "ng-bind " hoặc evaluation expressions^^

VD: one-way binding

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Example ng-bind</title>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js">
    var myApp = angular.module("myApp", []);
    myApp.controller("myController", function($scope){
        $scope.result = "abcxyz"
    });
    </script>
  </head>
  <body ng-app="myApp" controller="myController">
      <input ng-model="result" />
      {{result}}
  </body>
  </html>
  • Two way binding

Two_Way_Data_Binding.png

Nhìn vào đây bạn sẽ thấy quá trinh đồng bộ luôn xảy ra giữa model và view. Mọi sự thay đổi trong lớp này sẽ được cập nhật vào trong lớp kia. Scope trong controller sẽ được truyền tới View và ngược lại.

Scope Data : sẽ được truyền tới View và nếu data thay đổi thì nó sẽ lập tức truyền tới View và Data View sẽ thay đổi theo.

View Data: sẽ được truyền tới Scope/Controller và nếu data thay đổi thì nó sẽ lập tức truyền tới Scope và Scope Data sẽ thay đổi theo

Và chúng thường được sử dụng với "ng-model"

Ví Dụ thì mình đã lấy ở phần ví dụ của ng-bind phía trên rồi. Nhằm giải thích vì sao khi view thay đổi thì scope data cũng thay đổi theo.

  • One time binding Scope trong Controller sẽ được truyền tới View

Scope Data: sẽ truyền tới View nhưng chỉ lần đầu tiên và nếu data thay đổi thì nó cũng không thay đổi data view.

View Data: Scope Data sẽ không thay đổi với bất kỳ sự thay đổi dữ liệu nào trong data view

Và nó thường được sử dụng "::" như 1 phần của evaluation expressions

VD:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Example ng-bind</title>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js">
    var myApp = angular.module("myApp", []);
    myApp.controller("myController", function($scope){
        var counter = 0;
        var fruits= ['apple', 'lemon', 'meloon', 'pineapple', 'longan'];
        $scope.click = function(){
            $scope.fruit = fruits[counter % fruits.length];
            counter++;
        }
    });
    </script>
  </head>
  <body ng-app="myApp" controller="myController">
      <button ng-click="click()">Click</button>
      <p>One-time binding: {{ ::fruit }}</p>
      <p>Normal binding: {{ fruit }}</p>
      {{result}}
  </body>
  </html>

Directive ng-bind-html

Ví dụ trên ng-bind khi chúng ta muốn nhập trong input nội dung là 1 thẻ html. khi đó kết quả trả ra là dạng text và chúng không hiểu là ta đang nhập 1 thẻ html. Vậy muốn cho chúng hiểu được nội dung nhập là thẻ html và in ra dạng html chứ không phải dạng text thì chúng ta sẽ sử dụng ng-bind-html Để sử dụng được ng-bind-html thì phải add thêm 1 thử viện sanitize

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular-sanitize.js"></script>

và muốn sử dụng thư viện sanitize thì ta phải thêm vào danh sách các object trong module

VD:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Example ng-bind</title>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js"></script>
  </head>
  <body ng-app="">
      <input ng-model="result" />
      <div ng-bind-html="result">
  </body>
</html>

Directive ng-bind-template

Directive ng-bind-template là directive đặc biệt sẽ xác định nội dung cần replace thông qua biếu thức trong angular {{result}}. Điểm khác nhau giữa ng-bind-template và ng-bind là nó có thể chứa nhiều biểu thức `ng-bind-template="{{result1}}{{result2}}"

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Example ng-bind</title>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js"></script>
  </head>
  <body ng-app="">
      <input ng-model="result1" />
      <input ng-model="result2">
      <div ng-bind-template="{{result1}} {{result2}}">
  </body>
  </html>

Directive ng-model

ng-model dùng để liên kết dữ liệu với client chúng có nhiệm vụ trong angulerJS là :

  • Liên kết View trong model và một số directives khác như input, textarea hoặc select.
  • Cung cấp các thao thác validate dữ liệu như kiểm tra kiểu dữ liệu có phải là số, là email, ...
  • Kiểm soát thông tin từ client nhập vào có hợp lệ hay không và xuất thông báo lỗi
  • Thiết lập các css class trong thẻ HTML và tạo các hiệu ứng
  • ng-model sẽ cố gắng liên kết với các giá trị được khai báo (ví dụ {{name}}), nếu không tồn tại thì nó sẽ được tạo ngầm và lưu vào Scope. Điều này có nghĩa rằng nếu ta khai báo ng-model="somename" thì khi ứng dụng chạy lên trong $scope sẽ tồn tại một giá trị $scope.somename, nên trong controller ta muốn xử lý gán gái trị cho model thì chỉ cần dùng $scope để thay đổi. Ở ví dụ cuối cùng của bài này chúng ta có đề cập đến vấn đề này đấy.

Mình sẽ không đi vào cụ thể các chức năng trong ng-model vì trong bài viết này mình chỉ để cập đến ng-model trong Data Binding mà thôi

^^ mình tin sau khi đọc xong các ví dụ trên. Mọi người đã hiểu nhiệm vụ của ng-model trong data-binding rồi. và phần này mình sẽ không trình bày ví dụ cụ thể nữa.

ng-non-bindable

Khi mà {{ 1 + 2 }} được mình khai báo trong ng-app. và khi đó đoạn code của mình sẽ compile bởi AngularJS và sẽ được hiển thị trong HTML là 3 Vậy mình muốn hiển thị {{ 1 + 2 }} trong HTML thì mình sẽ làm cách nào? Đơn giản thôi. Angular cung cấp cho ta directive ng-non-bindable sẽ giúp cho đoạn mã code trong HTML không bị compile bởi AngularJS nữa.

VD:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Example ng-bind</title>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js"></script>
  </head>
  <body ng-app="">
      {{1+2}}
      <div ng-non-bindable>{{1+2}}</div>
      <div ng-bind-template="{{result1}} {{result2}}">
  </body>
  </html>

Vậy là mình đã trình bày sơ qua Data-Binding và các Drective được sử dụng trong Data Binding. Hẹn gặp lại các bạn ở bài viết sau. ^^


All Rights Reserved