【发布时间】:2015-08-12 20:37:45
【问题描述】:
假设我想要一个指令,它将用户输入的内容转换为小写。
所以我想出了这样的指令(在这个 Plunker http://plnkr.co/edit/jnE3s8MRr1tFCX0WVYel?p=preview 中):
app.directive('lowerCaseInput', function() {
return {
restrict: 'E',
template:'<input ng-model="vm.input" />',
scope: {},
require: ['ngModel', 'lowerCaseInput'],
controller:function() {},
link: function(scope, el, attrs, ctrls) {
var ngModel = ctrls[0], vm = ctrls[1];
ngModel.$render = render;
// view-> model
ngModel.$parsers.push(function(value) {
return toLowerCase(value);
});
// model->view
ngModel.$formatters.push(function(value) {
return value;
});
function render() {
vm.input = ngModel.$viewValue;
}
// view -> model && model-> view
function toLowerCase(value) {
return value && value.toLowerCase();
}
scope.$watch('vm.input', function(newVal, oldVal) {
if(newVal !== oldVal)
ngModel.$setViewValue(newVal);
});
},
controllerAs: 'vm'
}
})
但是,正如您在演示中看到的那样,模型值不会在初始传递时得到反映(变为全小写),因为从未触发 setViewValue。对于我确实希望指令根据某些规则更改模型的情况,我应该遵循一种通用方法吗?
此外,在用户实际与之交互之前,我希望避免将控件变为脏,所以即使我确实让它调用 $setViewValue 并导致 $parsers 管道,我希望它实现用户实际上并没有与它交互(因此保持它 $pristine)。
这可能吗?如果是这样,关于它的一些最佳实践是什么(比如可以从 $format 调用 $setViewValue -- 直接覆盖 ngModel 吗?等等......
【问题讨论】: