Angular输入指令组(二)
果然,程序花很少的时间能写出来,然后要花大量的时间去改bug。像我这种学什么都一知半解的程序员更是如此。在这里,我想说,上一篇博客中的输入指令组(一)中的代码是不完美的。
问题背景
问题出在哪呢?上午在本地环境测试的时候还是没问题的。但是,我们的程序是要和后台打交道的,此时,问题出现了。我们访问数据的方式都是异步的,也就是说,指令开始加载的时候数据还没有来,数据来了,指令已经加载好了。上午我在本地测试的时候,数据都是直接赋值,模拟过去的,所以没有什么问题。怪就怪在,同步世界的我根本没有考虑异步世界该如何处理。
问题描述
由于指令加载的时候此时ngModel中的数据还是空,所以显示的时候并不能获取到值。所以,显示出来都是清一色的未填写。
分析
那该如何处理呢,最理想的办法是把指令的加载放在ajax的回调函数中,哦?视图写在控制器的中。算了,不可能。
实在不行就得用$watch了,这似乎是万能的。
解决问题
$watch接受两个函数作为参数,一个是当做被监控函数,一个是动作函数。考虑监控函数返回什么,之前一直想在ngModel上做文章,奈何ngModel打印出来是一个构造函数,然后不知道为什么new还报错,所以慢慢对ngModel失去兴趣了。但是,我监控的内容肯定还是input所在的作用域所绑定的变量。
ngModel是一个指令,他的作用是让一个作用域对象和input元素进行双向绑定,ngModel的值就是模型。我们要监控的就是这个模型。
于是代码就是这样。
app.filter('show',function(){
return function(input){
if(input){
return input;
}else{
return "未填写";
}
}
});
app.directive('inputGroup',function($compile){
return {
restrict : 'A',
require : 'ngModel',
link : function(scope,element,attrs,ngModel){
var subScope = scope.$new(true);
subScope.label = attrs.label;
subScope.value = ngModel;
function toggleHiden(params){
for(var i in params)
params[i]
&& params[i].toggleClass
&& params[i].toggleClass("hidden");
}
subScope.edit = function(){
subScope.last = ngModel.$viewValue;
subScope.value = subScope.last;
toggleHiden(elements);
}
subScope.save = function(){
toggleHiden(elements);
}
subScope.cancel = function(){
subScope.value = subScope.last;
ngModel.$setViewValue(subScope.last);
element.val(subScope.last);
toggleHiden(elements);
}
var div = $compile('<div><div>')(subScope);
var label = $compile('<label>{{label}}</label>')(subScope);
var span = $compile('<span ng-click="edit()">{{value|show}}</span>')(subScope);
var save = $compile('<button ng-click="save()">保存</button>')(subScope);
var cancer = $compile('<button ng-click="cancel()">取消</button>')(subScope);
var elements = [element,save,span,cancer];
var hiddens = [element,save,cancer];
toggleHiden(hiddens);
div.attr('class',attrs.classname);
element.wrap(div);
element.after(label);
label.after(element);
element.after(span);
span.after(save);
save.after(cancer);
scope.$watch(function(){
return scope.$eval(attrs.ngModel);
},function(){
subScope.value = scope.$eval(attrs.ngModel);
});
}
}
});
这是控制器代码
<script>
var app = angular.module('app',[]);
app.controller('testCtrl',function($http){
var vm = this;
var param = {time: "2016-10-17T13:29:52.344Z"};
//基本的
$http.post('/apis/anti/time',param).success(function(data){
vm.time = data;
});
vm.a = 1;
vm.b = 2;
});
</script>
视图是这样
<input type="text" ng-model="vm.time" input-group label="用户名" classname="anti">
<input type="text" ng-model="vm.b" input-group label="用户名" classname="anti">
{{vm|json}}
注意:在控制器中我请求了后台的数据,如果是为了写demo完全可以用本地的json代替。相比上一个版本,又考虑了很多新的东西。对$watch和link函数的理解又深了一些。