我试图通过实现一个指令来获取和设置视图/模型的值,从而获得对ng-model的getter / setter支持。我几乎就在那里,但最终我的无限$ digest循环。
想法是设置ng-model =“$ someFieldToStoreInTheScope”,然后让getter / setter指令在该字段和getter / setter函数之间进行更新。
当ngModelController更新范围中的字段时,我使用$ watch使用setter表达式更新模型,当getter表达式更改时,使用另一个watch更新该字段。
查看:http://jsfiddle.net/BDyAs/10/
HTML:
<div ng-app="myApp">
<body>
<form name="form">
<input type="text" ng-model="$ngModelValue" ng-model-getter-setter="get=getValue();set=setValue($value)"/> {{myDerivedValue}}
</form>
</body>
</div>
JS:
var myApp = angular.module('myApp', []);
myApp.directive(
{
'ngModelGetterSetter': function () {
return {
require: "ngModel",
controller: ctrl,
link: function(scope, element, attrs, ngModelCtrl)
{
var getterSetterExpression = attrs.ngModelGetterSetter;
var tokens = getterSetterExpression.split(";");
var getExpression = tokens[0].split("=")[1];
var setExpression = tokens[1].split("=")[1];
function updateViewValue()
{
var updateExpression = attrs.ngModel + "=" + getExpression;
scope.$eval(updateExpression);
}
function updateModelValue()
{
scope.$value = ngModelCtrl.$viewValue;
scope.$eval(setExpression);
}
updateViewValue();
scope.$watch(getExpression, updateViewValue);
scope.$watch(attrs.ngModel, updateModelValue);
}
};
}
});
function ctrl($scope) {
$scope.getValue = function ()
{
return $scope.myValue;
}
$scope.setValue = function (val)
{
$scope.myValue = val;
$scope.myDerivedValue = $scope.myValue * 2;
}
$scope.setValue(5);
setInterval(function () { $scope.setValue($scope.getValue() + 1); $scope.$apply(); }, 1000);
}
我在代码中放了一个setInterval()来修改模型,看看它是否在视图中正确传播。
知道为什么有一个无限的摘要循环,以及如何删除它?
答案 0 :(得分:8)
注意 AngularJs 1.3现在支持ng-model的Getter / Setter。有关详细信息,请参阅http://docs.angularjs.org/api/ng/directive/ngModelOptions。
我可以通过额外调用来打破无限循环
ngModelCtrl.$setViewValue()
和
ngModelCtrl.$render()
在事件处理程序中。不确定这是否是最佳方式。
请参阅小提琴:http://jsfiddle.net/BDyAs/12/
修改强>
我在
中进一步改进了代码通过将指令分离为getter和setter的单独指令。
答案 1 :(得分:2)
我认为关于打破摘要循环的问题已得到解答。对于同样的问题,这是一种不同的,更清晰的方法,不涉及$watch
。
如果您不需要支持旧版浏览器,请使用ECMAScript 5访问者。
只需向角度控制器添加属性:
Object.defineProperty(
$scope,
"accessorWrappedMyValue",
{
get : function() { return $scope.myValue; },
set : function(newValue) {
$scope.myValue = newValue;
$scope.myDerivedValue = $scope.myValue * 2;
},
configurable: true
});
现在您需要做的就是accessorWrappedMyValue
引用ng-model
,如下所示:
<input type="text" ng-model="accessorWrappedMyValue" />
This blog对ES5访问器有一个很好的介绍。
使用this feature matrix决定是否可以使用ES5。有趣的行是&#34; Getter / Setter in property initializer&#34;和&#34; Object.defineProperty&#34;。