openplanning

Hướng dẫn và ví dụ AngularJS Directive

  1. Directive là gì?
  2. Directive với templateUrl

1. Directive là gì?

Directive (Chỉ thị) trong AngularJS là gì? Có nhiều câu trả lời cho câu hỏi này mà bạn có thể tìm thấy trên Google, chỉ có điều nó quá dài dòng, và tôi thích một câu trả lời ngắn gọn hơn.
  • Directive là một chỉ dẫn để bạn tạo ra một "Cái mới". "Cái mới" ở đây có thể là một thẻ (tag) mới, hoặc tạo một thuộc tính (attribute) mới cho một thẻ, hoăc tạo một lớp CSS mới, hoặc tạo một Comment (Chú thích).
  • Đồng thời Directive chỉ dẫn cho AngularJS cách để chuyển đổi "Cái mới" đó thành mã HTML mà trình duyệt có thể hiểu.
Ví dụ, Tôi tạo một Directive tên là "helloWorld" để định nghĩa ra một thẻ mới là <hello-world>, và tôi sử dụng thẻ mới này trong tập tin HTML. Trình duyệt rõ ràng không hiểu thẻ này, nhưng khi tập tin được chạy trên trình duyệt, AngularJS sẽ dựa trên chỉ dẫn của Directive ở trên để chuyển đổi thẻ <hello-world> thành mã HTML mà trình duyệt có thể hiểu.
Directive E (Element):
Không có gì tốt hơn là bắt đầu với một ví dụ. Làm sao tôi có thể tạo ra một thẻ (tag) mới?
Trên một thư mục bất kỳ bạn tạo 2 tập tin directive-e-example.html & directive-e-example.js:
directive-e-example.js
// Create an Application named "myApp"
var app = angular.module("myApp", []);

// Create a Directvie named "helloWorld"
app.directive("helloWorld", function() {
    return {
        restrict : "E",
        template : "<h1>Hello World!</h1>"
    };
});
Trong tập tin Javascript ở trên, đầu tiên tạo một module (app), sau đó tạo một Directive có tên helloWorld cho module này. Tên của một Directive phải theo quy tắc camelCase.
  • Các cách đặt tên trong các ngôn ngữ lập trình
directive-e-example.html
<!DOCTYPE html>
<html>
   <head>
      <title>AngularJS Directive</title>
      <!-- Check version: https://code.angularjs.org/ -->
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.2/angular.min.js"></script>
      <script src="directive-e-example.js"></script>
   </head>
   <body>
      <div ng-app="myApp" ng-controller="myCtrl">
         <h3>Directive E (Element):</h3>

         <hello-world></hello-world>

      </div>
   </body>
</html>
Mở tập tin directive-e-example.html trên trình duyệt, và bạn có kết quả như sau:
Directive A (Attribute)
Trong ví dụ này tôi sẽ tạo thuộc tính có tên good-bye cho một thẻ của HTML:
Chúng ta sẽ tạo 2 tập tin directive-a-example.html & directive-a-example.js:
directive-a-example.js
// Create an Application named "myApp"
var app = angular.module("myApp", []);

// Create a Directvie named "helloWorld"
app.directive("goodBye", function() {
    return {
        restrict : "A",
        template : "<h1>Good Bye!</h1>"
    };
});
directvie-a-example.html
<!DOCTYPE html>
<html>
   <head>
      <title>AngularJS Directive</title>
      <!-- Check version: https://code.angularjs.org/ -->
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.2/angular.min.js"></script>
      <script src="directive-a-example.js"></script>
   </head>
   <body>
      <div ng-app="myApp" ng-controller="myCtrl">
         <h3>Directive A (Attribute):</h3>

         <div good-bye></div>

      </div>
   </body>
</html>
Mở tập tin directive-a-example.html trên trình duyệt, và nhận được kết quả:
Directive C (Class)
directive-c-example.js
// Create an Application named "myApp"
var app = angular.module("myApp", []);

// Create a Directvie named "errMessage"
app.directive("errMessage", function() {
    return {
        restrict : "C",
        template : "<h1>Something Error!</h1>"
    };
});
directive-c-example.html
<!DOCTYPE html>
<html>
   <head>
     <title>AngularJS Directive</title>
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.2/angular.min.js"></script>
      <script src="directive-c-example.js"></script>
   </head>
   <body>
      <div ng-app="myApp" ng-controller="myCtrl">
         <h3>Directive C (Class):</h3>

        <div class="err-message"></div>

      </div>
   </body>
</html>
Directive M (Comment)
directive-m-example.js
// Create an Application named "myApp"
var app = angular.module("myApp", []);

// Create a Directvie named "myComment"
app.directive("myComment", function() {
    return {
        restrict : "M",
        replace : true,
        template : "<h1>OK Important!</h1>"
    };
});
directive-m-example.html
<!DOCTYPE html>
<html>
   <head>
     <title>AngularJS Directive</title>
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.2/angular.min.js"></script>

      <script src="directive-m-example.js"></script>
   </head>
   <body>
      <div ng-app="myApp" ng-controller="myCtrl">
         <h3>Directive M (Comment):</h3>

        <!-- directive: my-comment -->

      </div>
   </body>
</html>

2. Directive với templateUrl

Thông thường khi bạn tạo một Directive bạn phải cung cấp một nội dung HTML thông qua thuộc tính (property) "template". Nếu nội dung HTML quá dài nó sẽ là một rắc rối, trong trường hợp này bạn nên đặt nội dung HTML này vào một tập tin, sau đó sử dụng thuộc tính (property) "templateUrl" để trỏ đến vị trí của tập tin đó.
Trong ví này, tôi có một dữ liệu là các công việc cần phải làm, và tôi sẽ tạo một Directive có tên "myTodoList". Dữ liệu sẽ được hiển thị trên giao diện giống hình minh họa dưới đây:
todo-template.html
<div class="my-todo-list">
  <h1>{{title}}</h1>

  <div ng-repeat="todo in todoList">
    <input type="checkbox" ng-model="todo.completed"> {{todo.name}}
  </div>

</div>
todo-example.js
var app = angular.module("myApp", []);

var ctrl = app.controller("myCtrl", function($scope) {

  $scope.todoDatas = [
    {name: 'Create a custom directive', completed: true},
    {name: 'Learn about restrict', completed: true},
    {name: 'Master scopes', completed: false}
  ];

});

// Create a Directive named "myTodoList"
// E: Element <my-todo-list todo-list="=" title="@">
app.directive("myTodoList", function() {
    return {
        restrict : "E",
        templateUrl : "todo-template.html",
        // '=' : an expression
        // '@': a string
        scope: {
          todoList: '=',
          title: '@'
        }
    };
});
todo-example.html
<!DOCTYPE html>
<html>
   <head>
      <title>AngularJS Directive</title>
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.2/angular.min.js"></script>
      <script src="todo-example.js"></script>
      <style>
         .my-todo-list  {
           border: 1px solid #ddd;
           padding: 5px;
           margin: 5px;
           width: 320px;
         }
      </style>
   </head>
   <body>
      <div ng-app="myApp">
         <div  ng-controller="myCtrl">
            <h2>Custom Directive with templateUrl</h2>

            <!-- $scope.todoDatas -->
            <my-todo-list todo-list="todoDatas" title="My Todo List"/>

         </div>
      </div>
   </body>
</html>
Bạn cần chạy tập tin todo-example.html trên một HTTP Server, điều này là bắt buộc bởi vì templateUrl yêu cầu nguồn dữ liệu phải đến từ http hoặc https, nó không chấp nhận nguồn dữ liệu đến từ file:///.
OK, tôi sẽ giải thích code của ví dụ trên:
Hình minh họa ở trên cho thấy rằng chúng ta đang tạo một Directive có tên "myTodoList", nó giống như bạn tạo ra một thẻ mới <my-todo-list> với 2 thuộc tính todo-list & title.
  • '@' ám chỉ rằng nó là một String.
  • '=' ám chỉ rằng nó là một biểu thức (Expression).