自定义Directive使用ngModel
我们知道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)