我有各种输入(包括稍后将解释的指令),例如:
<input mask-value="ssn" validate="checkSsn"/>
<input mask-value="pin" validate="checkPin"/>
这些属性位于控制器中:
app.controller("Ctrl", ['$scope', function ($scope) {
$scope.ssn = "";
$scope.pin = "";
$scope.checkSsn = function () { /* validate $scope.ssn */ };
$scope.checkPin = function () { /* validate $scope.pin */ };
}]);
最后,maskValue
指令:
app.directive("maskValue", function () {
return function (scope, element, attrs) {
/* does some focus/blur magic and string replacement */
scope[attrs.maskValue] = this.value;
scope[attrs.validate]();
};
});
这有效,但似乎是对我滥用Angular。相反,使用隔离范围更有意义,如:
scope: {validate: "&"}
然后我可以使用scope.validate()
代替scope[attrs.validate]()
。 然而,隔离范围我无法更新控制器中的相应值。使用{maskValue: "="}
不起作用,因为这会尝试更新父项的maskValue
属性而不是特定值。我认为使用{ssn: "="}
会起作用,但是我必须更新控制器的特定属性,而不是将其设置为指令属性,这将使指令不灵活。显然也不建议使用$parent
。
如何在隔离范围指令内动态访问控制器的属性?
编辑:我无法在输入中使用ng-model=ssn
等,因为在mask-value
中的焦点/模糊事件期间,输入的实际值会发生变化。例如,它可能变为*****####
,但我需要在某处存储实际值#########
,并且控制器似乎是合适的位置,因为控制器稍后会出于其他原因使用它。
答案 0 :(得分:2)
<div ng-app=foo>
<div ng-controller=Ctrl>
{{ssn}}
<input mask-value="ssn" validate="checkSsn()">
app = angular.module("foo", []);
app.controller("Ctrl", ['$scope', function ($scope) {
$scope.ssn = "";
$scope.checkSsn = function () { console.log($scope.ssn); };
}]);
app.directive("maskValue", function () {
return {
scope: {
validate: "&",
maskValue: "="
},
link: function (scope, element, attrs) {
element.bind("change", function () {
scope.maskValue = this.value;
scope.$apply();
scope.validate();
});
},
};
});
编辑:
他们说最好将要评估的表达式作为参数传递给$apply
,因为在Anguular中有一些错误处理特性:
var value = this.value;
scope.$apply(function () {
scope.maskValue = value;
});
答案 1 :(得分:1)
我知道你已经得到了问题的答案,但我认为值得一提的是,既然你似乎正在做一些验证,你可以使用Angular的内置功能来做到这一点,但仍然可以使用{ {1}}。这是一个例子:
ng-model
此指令使用NgModelController以便与app.directive("maskValue", function ($parse) {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, ngModel) {
if (!ngModel) return;
var validator = $parse(attrs.validator)(scope);
ngModel.$render = function() {
var hasFocus = document.activeElement == element[0];
if (ngModel.$valid || hasFocus) element.val(ngModel.$modelValue)
else element.val('#######');
};
element.bind('blur', function() {
ngModel.$setValidity('maskValue', validator(this.value))
ngModel.$render();
});
element.bind('focus', function() {
ngModel.$render();
});
}
};
});
一起控制视图的更新方式。在这个人为的例子中,当元素失去焦点并且验证函数返回false时,它将简单地呈现########。但是当控件再次聚焦时,它将呈现其真正的价值,以便用户可以更改它。请注意,绑定到控件的作用域的属性保持不变,而其视图相应地更改为元素状态(有效或无效)。您可以看到一个有效的示例here。
答案 2 :(得分:0)
我很抱歉,为什么不这样做呢:
app = angular.module("foo", []);
app.controller("Ctrl", ['$scope', function ($scope) {
$scope.ssn = "";
$scope.validate = function () { console.log($scope.ssn); };
}]);
app.directive("maskValue", function () {
return {
link: function (scope, element, attrs) {
element.bind("change", function () {
scope.validate();
});
},
};
});
和HTML一样:
<div ng-app=foo>
<div ng-controller=Ctrl>
<input ng-model="ssn" mask-value />
</div>
</div>