我們知道ngModel是AngularJS中預設的一個Directive,用於資料的雙向繫結。通常是這樣使用的:
<input type="text" ng-model="customer.name" />
在控制器中大致這樣:
$scope.customer ={
name: ''
}
在上一篇中,有關表格的Directive是這樣使用的:
<table-helper datasource="customers" clumnmap="[{name: 'Name'}, {street: 'Street'}, {age: 'Age'}, {url: 'URL', hidden: true}]"></table-helper>
以上,datasource代表資料來源,是否可以用ng-model替代呢?
比如寫成這樣:
<table-helper-with-ng-model ng-model="customers" columnmap="[{name:'Name'}...]">
</table-helper-with-ng-model>
可是,自定義的tableHelper這個Direcitve如何獲取到ngModel中的值呢?
這就涉及到Direcitve之間的通訊了,就像在"AngularJS中Directive間互動實現合成"說的。
要解決的第一個問題是:如何拿到ngModel?
--使用require欄位
return { restrict: 'E', required: '?ngModel', //^ngModel本級或父級, ^^ngModel父級 scope: { columnmap: '=' }, link: link, template: template }
要解決的第二個問題是:如何從ngModel這個Direcitve拿資料?
--使用ngModel.$modelValue
要解決的的第三個問題是:當ngModel值變化,如何告之外界並重新載入表格?
--大致有4種方法
//1 觀察某個屬性的值 attrs.$observe('ngModel', function(value){ //監視變數的值 scope.$watch(value, function(newValue){ render(); }); }); //2 或者 scope.$watch(attrs.ngModel, render); //3 或者 scope.$watch(function(){ return ngModel.$modelValue; }, function(newValue){ render(); }) //4 或者 ngModel.$render = function(){ render(); }
相對完整的程式碼如下:
var tableHelperWithNgModel = function(){ var dataSource; var template = '<div class="tableHelper"></div>'; var link = function(scope, element, attrs, ngModel){ ... function render(){ if(ngModel && ngModel.$modelValue.length){ datasource = ngModel.$modelValue; table += tableStart; table += renderHeader(); table += renderRows() + tableEnd; renderTable(); } } }; return { restrict: 'E', required: '?ngModel', //^ngModel本級或父級, ^^ngModel父級 scope: { columnmap: '=' }, link: link, template: template } } angular.module('direcitveModule') .directive('tableHelperWithNgModel', tableHelperWithNgModel) var tableHelperWithNgModel = function(){ var dataSource; var template = '<div class="tableHelper"></div>'; var link = function(scope, element, attrs, ngModel){ //觀察某個屬性的值 attrs.$observe('ngModel', function(value){ //監視變數的值 scope.$watch(value, function(newValue){ render(); }); }); //或者 scope.$watch(attrs.ngModel, render); //或者 scope.$watch(function(){ return ngModel.$modelValue; }, function(newValue){ render(); }) //或者 ngModel.$render = function(){ render(); } function render(){ if(ngModel && ngModel.$modelValue.length){ datasource = ngModel.$modelValue; table += tableStart; table += renderHeader(); table += renderRows() + tableEnd; renderTable(); } } }; return { restrict: 'E', required: '?ngModel', //^ngModel本級或父級, ^^ngModel父級 scope: { columnmap: '=' }, link: link, template: template } } angular.module('direcitveModule') .directive('tableHelperWithNgModel', tableHelperWithNgModel)