AngularJS directive
Bài đăng này đã không được cập nhật trong 8 năm
I. Directive và một số khái niệm
- Directive là những "Marker" trong một DOM (các thuộc tính, tên của các element hay CSS class...) và nó được kèm theo một số hành vi đặc biệt hay thậm chí nó còn thay đổi các thành phần DOM hay chính các thành phần con của nó.
Angular có một số directive built-in có sẵn như
ngBind
,ngModel
vàngClass
... ngoài ra bạn cũng có thể tự chế cho mình một directive riêng. - Matching Directive: Một element được coi là match với directive nếu directive được khai báo, sử dụng trong html element ví dụ:
<input ng-model="foo">
Input element matches với ngModel
- Normalization:
Angular normalize là một tag hay tên của attribue để xác định được những thành phần nào được match với directive nào. Thông thường chúng ta thường sử dụng camelCase (eg. ngClass, ngModel ..), thế nhưng đối với HTML ta hay dùng
dash-delimited
attributes ở trên DOM (e.g. ng-model) - Normalization process:
- Cắt bỏ
x-
,data-
của html element/attribute - Convert
:
,-
,_
thành camelCase ví dụ
- Cắt bỏ
<div ng-controller="Controller">
Hello <input ng-model='name'> <hr/>
<span ng-bind="name"></span> <br/>
<span ng:bind="name"></span> <br/>
<span ng_bind="name"></span> <br/>
<span data-ng-bind="name"></span> <br/>
<span x-ng-bind="name"></span> <br/>
</div>
Tất cả các element trên sẽ được match với ngBind
directive
II. Thành phần bên trong directive
II.1 Tạo directive
Cũng giống như controller, directive cũng phải registered với module. Đăng ký directive với cú pháp:
module.directive
Nó sẽ tạo ra một normalized directive và kèm theo một factory function. Factory này trả về một object với nhiều option khác nhau.
Và factory fuction này được gọi mỗi khi compiler
match với directive ở lần đầu tiên.
Chú ý: Khi tạo directive bạn nên tạo ra một directive có tiền tố của riêng bạn để tránh việc xung đột với các thẻ html đặc biệt là không được tạo directive với tiền tố là ng
.
II.2 Template
.directive('myCustomer', function() {
return {
template: 'Name: {{customer.name}} Address: {{customer.address}}'
};
})
và trên html sẽ gọi
<div ng-controller="Controller">
<div my-customer></div>
</div>
Sau khi $compile
compile và link tới <div -my-customer> </div>
. $compile
sẽ tìm và match với directive của những thành phần con, điều đó có nghĩa là bạn có thể tạo ra một directive từ một directive khác.
Thông thường nội dung của template lớn thì ta có thể dùng templateUrl rồi link tới một file html
.directive('myCustomer', function() {
return {
templateUrl: 'my-customer.html'
};
});
templateUrl
có thể là một function trả về một URL của html. Angular sẽ gọi templateUrl function với 2 tham số. Một là element và attr
, là object có liên kết với element đó.
Chú ý: Không truy cập được scope
từ templateUrl function, do đó template sẽ được yêu cầu trước khi scope
được khởi tạo.
.directive('myCustomer', function() {
return {
templateUrl: function(elem, attr){
return 'customer-'+attr.type+'.html';
}
};
});
Một chú ý khác đó là khi tạo một directive, nó sẽ được mặc định restricted cho attributes hoặc element. Restrict option: - A: chỉ match với attributes name - E: chỉ match với element name - C: chỉ match với class name - M: chỉ match với comment
.directive('myCustomer', function() {
return {
restrict: 'E',
templateUrl: 'my-customer.html'
};
});
II.3 Isolating Scope của một Directive
Isolating scope là việc tách biệt scope bên trong directive không còn phụ thuộc vào scope bên ngoài nữa, sau đó sẽ map scope bên ngoài vào scope bên trong directive. Để làm được việc đó thì ta sử dụng option scope
bên trong directive.
.directive('myCustomer', function() {
return {
restrict: 'E',
scope: {
customerInfo: '=info'
},
templateUrl: 'my-customer-iso.html'
};
});
<div ng-controller="Controller">
<my-customer info="naomi"></my-customer>
<hr>
<my-customer info="igor"></my-customer>
</div>
Như đã thấy 2 element trên có attributes info="naomi"
và info="igor"
scope: {
customerInfo: '=info'
},
Scope option là một đối tượng có chứa một thuộc tính cho mỗi một isolate scope binding. Như ví dụ trên thifh nó có một thuộc tính
- Tên: customerInfo
tương ứng với isolae scope property của directive customerInfo
- Giá trị: =info
cho $compile
biết để bind với thuộc tính info
Trong trường hợp tên của attributes trùng với giá trị mà bạn muốn bind ở trong directive scope, có thể dùng cú pháp ngắn gọn sau
...
scope: {
// same as '=customer'
customer: '='
},
....
II.4 Directive thao tác với DOM
- Directive sử dụng
link
option để thao tác với DOM ( register DOM listener cũng như update DOM). Nó được thực thi sau khi tempate đã được clone link
là một functionfunction link(scope, element, attrs, controller, transcludeFn) { ... }
trong đó:
scope
là một đối Angular scopeelement
là một element mà directive sẽ matchattrs
là một hash object của normalize attribute name và valuecontroller
controller được required bởi directive
link : function(scope, element, attrs){
element.on('click', function(event) {
//Update DOM.
element.html('Thanks for buying this item.');
element.css({
color: 'green'
});
});
}
Nguồn tham khảo
https://docs.angularjs.org/guide/directive
https://www.sitepoint.com/practical-guide-angularjs-directives-part-two/
All rights reserved