我不清楚scope.ngModel
和controller.$viewValue
/ controller.$modelValue
/ controller.$setViewValue()
之间的关系是什么,具体而言,后三者的关系是什么。例如,请参阅this jsfiddle:
<input type="text" ng-model="foo" my-directive>
和
myApp.directive('myDirective', function($timeout) {
return {
require: 'ngModel',
restrict: 'A',
scope: { ngModel: '=' },
link: function (scope, element, attrs, controller) {
function log() {
console.log(scope.ngModel);
console.log(controller.$viewValue);
console.log(controller.$modelValue);
}
log();
controller.$setViewValue("boorb");
log();
scope.$watch('ngModel', function (val) {
console.log("val is now", val);
});
$timeout(function () {
log();
}, 2000);
}
}
});
控制器为:
function MyCtrl($scope, $timeout) {
$scope.foo = 'ahha';
$timeout(function () {
$scope.foo = "good";
}, 1000);
}
输出结果为:
(index):45 ahha
(index):46 NaN
(index):47 NaN
(index):45 ahha
(index):46 boorb
(index):47 boorb
(index):53 val is now ahha
(index):53 val is now good
(index):45 good
(index):46 boorb
(index):47 boorb
controller.$viewValue
并未以foo
变量的值开头。此外,controller.$setViewValue("boorb")
根本不会影响scope.ngModel
,也不会在HTML中反映更新。因此,似乎scope.ngModel
和controller.$viewValue
之间没有关系。似乎有任何我想做的事情,我只会使用scope.ngModel
,并观察这些值。使用controller.$viewValue
和controller.$modelValue
或使其与scope.ngModel
保持同步有什么意义?
答案 0 :(得分:0)
scope: { ngModel: '=' },
为指令创建了一个独立的范围,这意味着指令中对foo
的更改将不再反映在MyCtrl
的父范围内。
此外,$setViewValue()
所做的更改在调用controller.$render()
之前不会反映在DOM中,这会告诉Angular在下一个摘要周期中更新DOM。
但是要回答这个问题,NgModelController
及其方法实际上只有在你需要创建一些特殊的自定义数据绑定指令时才是必需的。对于正常的数据输入和验证,您不应该使用它。来自the documentation(强调我的):
[NgModelController]包含用于数据绑定,验证,CSS更新以及值格式化和解析的服务。它故意不包含任何处理DOM呈现或侦听DOM事件的逻辑。这种与DOM相关的逻辑应该由其他指令提供,这些指令利用NgModelController对控制元素进行数据绑定。 Angular为大多数输入元素提供了这个DOM逻辑。
答案 1 :(得分:0)
这里的困惑来自于将指令粘贴到现有指令上,即ngInput
。
相反,请考虑一个新指令:
<my-directive ng-model="ugh">Sup</my-directive>
使用:
$rootScope.ugh = 40;
和
.directive('myDirective', function () {
return {
require: "ngModel",
// element-only directive
restrict: "E",
// template turns the directive into one input tag
// 'inner' is on the scope of the *directive*
template: "<input type='text' ng-model='inner'/>",
// the directive will have its own isolated scope
scope: { },
link: function (scope, element, attrs, ngModelCtrl) {
// formatter goes from modelValue (i.e. $rootScope.ugh) to
// view value (in this case, the string of twice the model
// value + '-'
ngModelCtrl.$formatters.push(function (modelValue) {
return ('' + (modelValue * 2)) + '-';
});
// render does what is necessary to display the view value
// in this case, sets the scope.inner so that the inner
// <input> can render it
ngModelCtrl.$render = function () {
scope.inner = ngModelCtrl.$viewValue;
};
// changes on the inner should trigger changes in the view value
scope.$watch('inner', function (newValue) {
ngModelCtrl.$setViewValue(newValue);
});
// when the view value changes, it gets parsed back into a model
// value via the parsers, which then sets the $modelValue, which
// then sets the underlying model ($rootScope.ugh)
ngModelCtrl.$parsers.push(function (viewValue) {
var sub = viewValue.substr(0, viewValue.length-1);
return parseInt(sub)/2;
});
}
};
})
在Plunker上试用。
请注意typeof ugh
保持"number"
,即使指令的视图值属于不同类型。