AngularJS 指令双向数据绑定在观察布尔值时不起作用
AngularJS Directive Two-Way Data Binding Not Working When Observing Boolean
我有一个双向数据绑定,它不会改变发送到指令的变量值。
我的指令监视触发器并将焦点放在关联元素上(基于在此处找到的代码):
app.directive('focusMe', function ($timeout) {
return {
scope: {
trigger: '=focusMe'
},
link: function (scope, element, attrs) {
scope.$watch('trigger', function(value) {
console.log("directive value: " + value);
console.log("directive start: " + scope.trigger);
if (value === true) {
$timeout(function () {
element[0].focus();
scope.trigger = false;
console.log("directive end: " + scope.trigger);
});
}
});
}
}
});
在HTML中我这样称呼它:
<input type="text" ng-model="item.value" focus-me="focusInput" />
当我第一次触发它时,它起作用了——因为 focusInput
变量改变了它的值。但是当指令完成时,控制器范围内的 focusInput
(指令外)不会切换回 false
。
当我调用 scope.trigger = false
时应该切换回 false
,假设我理解应该发生的事情。
缺少什么会导致双向绑定不将值推回传递给指令的变量?
更新 01:
为了发布问题,我删除了一小部分代码。 HTML 实际上是这样的:
<input type="text" ng-model="item.value" focus-me="focusInput" ng-if="item.condition != 'matches' && item.condition != 'does not match'" />
如果 input
字段隐藏然后重新显示(基于 ng-if
),该指令将在第一次 focusInput
更改时正确给予焦点。之后它将再次停止工作...除非重复 hide/show 过程。
您遇到的问题是在范围内处理原始值(布尔值、整数等)时的常见问题。
我强烈建议阅读 Understanding Scopes 文章。 (简短回答:原语在指令的隔离范围内发生更改,并且不会在父范围的链中查找,即您的控制器范围)。
至于如何解决你的情况,我建议使用点符号并将你的原语存储在一个对象中,并将这个对象绑定到你的指令:
scope: {
triggerObj: '=focusMe'
},
并确保指令中的触发器引用现在是 scope.triggerObj.trigger
。
并且在您的控制器中有:
$scope.triggerObj = {};
$scope.triggerObj.trigger = true; //or false, what have you
拥有对象将确保双向绑定有效。并在有空的时候阅读上面的文章:)
指令创建范围。当您将参数传递给作用域时,对象通过引用传递,布尔值(以及数字、字符串...)通过值传递。
例如:
function changeToFalse(bool) {
bool= false;
console.log(bool); // false
}
function changeObjToFalse(obj) {
obj.bool= false;
console.log(obj.bool); // false
}
var obj = {bool : true};
changeToFalse(obj.bool);
console.log(obj.bool); // true
changeObjToFalse(obj);
console.log(obj.bool); // false
另见相同问题 - two way binding not working with ng-repeat。
我有一个双向数据绑定,它不会改变发送到指令的变量值。
我的指令监视触发器并将焦点放在关联元素上(基于在此处找到的代码):
app.directive('focusMe', function ($timeout) {
return {
scope: {
trigger: '=focusMe'
},
link: function (scope, element, attrs) {
scope.$watch('trigger', function(value) {
console.log("directive value: " + value);
console.log("directive start: " + scope.trigger);
if (value === true) {
$timeout(function () {
element[0].focus();
scope.trigger = false;
console.log("directive end: " + scope.trigger);
});
}
});
}
}
});
在HTML中我这样称呼它:
<input type="text" ng-model="item.value" focus-me="focusInput" />
当我第一次触发它时,它起作用了——因为 focusInput
变量改变了它的值。但是当指令完成时,控制器范围内的 focusInput
(指令外)不会切换回 false
。
当我调用 scope.trigger = false
时应该切换回 false
,假设我理解应该发生的事情。
缺少什么会导致双向绑定不将值推回传递给指令的变量?
更新 01:
为了发布问题,我删除了一小部分代码。 HTML 实际上是这样的:
<input type="text" ng-model="item.value" focus-me="focusInput" ng-if="item.condition != 'matches' && item.condition != 'does not match'" />
如果 input
字段隐藏然后重新显示(基于 ng-if
),该指令将在第一次 focusInput
更改时正确给予焦点。之后它将再次停止工作...除非重复 hide/show 过程。
您遇到的问题是在范围内处理原始值(布尔值、整数等)时的常见问题。
我强烈建议阅读 Understanding Scopes 文章。 (简短回答:原语在指令的隔离范围内发生更改,并且不会在父范围的链中查找,即您的控制器范围)。
至于如何解决你的情况,我建议使用点符号并将你的原语存储在一个对象中,并将这个对象绑定到你的指令:
scope: {
triggerObj: '=focusMe'
},
并确保指令中的触发器引用现在是 scope.triggerObj.trigger
。
并且在您的控制器中有:
$scope.triggerObj = {};
$scope.triggerObj.trigger = true; //or false, what have you
拥有对象将确保双向绑定有效。并在有空的时候阅读上面的文章:)
指令创建范围。当您将参数传递给作用域时,对象通过引用传递,布尔值(以及数字、字符串...)通过值传递。
例如:
function changeToFalse(bool) {
bool= false;
console.log(bool); // false
}
function changeObjToFalse(obj) {
obj.bool= false;
console.log(obj.bool); // false
}
var obj = {bool : true};
changeToFalse(obj.bool);
console.log(obj.bool); // true
changeObjToFalse(obj);
console.log(obj.bool); // false
另见相同问题 - two way binding not working with ng-repeat。