说我们有这个表达
$scope.showButton = users.is_admin() && !document.is_provided;
然后在同一个控制器中,您有一个更新Document.is_provided
的值的按钮:
<button ng-click="document.is_provided = true;">Provide document</button>
问题在于$scope.showButton
现在应该改变,但它没有改变。
更新: Plnkr显示简化问题:http://plnkr.co/edit/Qk2jnHAmqsrNXSAjDYEk?p=preview
答案 0 :(得分:4)
我想补充一下squiroid的答案并向你解释它为何有效。我将为您提供一种非常简单的理解方式,因为这对我来说也是一个非常常见的问题。
Angular有一个叫做Digest循环的东西。它是一系列连续调用的函数,以确保如果变量A与另一个变量B双向绑定(例如使用ng-model),它们始终保持同步(即,始终具有相同的值) )。 angular提供的函数(或通常以$开头的服务,如$ timeout等)自动启动摘要周期
所以让我们假设你有一个变量A并且你将它绑定到$ scope变量B,它等于变量C.你会期望C也被绑定到A,对吧?因为你认为当你改变C时,B应该改变,所以A也应该改变。但这只有在您开始摘要周期时才有可能。该循环将查找需要更新的变量,并将更新它们。但是,只需更改C的值,就不会触发摘要周期,因此您的更改永远不会传播到A.
当你在$ watch中添加一个变量时你做的是(如$建议的那样),你强行启动一个摘要周期。所以现在当你改变C时,你开始循环,它追踪它也需要更新A,这就是它的工作原理。
在您的示例中,$ scope.showButton绑定到document.is_provided。现在,您正在使用非角度函数来更改document.is_provided的值。这意味着您不会触发摘要周期,这意味着您的更改永远不会传播到$ scope.showButton。因此,showButton始终保持错误。
当然,还有一个例子可以帮助您理解: http://jsbin.com/vojoso/edit?js,console,output
观看控制台。我添加了日志以帮助您理解。 注释掉$ watch语句,看看会发生什么。 尝试理解它然后自己做,你会得到它。
希望我帮助过:)
答案 1 :(得分:3)
我不确定,但你可以看一下: -
$scope.$watch(function(){
return Users.is_admin() && !Document.is_provided;
},fuction(newVal){
$scope.showButton =newVal;
});
希望有所帮助:)
答案 2 :(得分:2)
以下是关于$scope.$watch的好文章,它应该有助于了解如何解决您的问题。
你需要更大的答案添加代码来解释Document
变量和你的REST服务。
UPD:我看到你改变了原来的问题。我想你的控制器有问题。请尝试隐式使用$scope
,将data
属性视为悲伤angular code style
同时显示模板中连接控制器的部分。
UPD 2:你对我的话有些误解,所以我修改了你的plunker example
<强>的index.html 强>
<html ng-app="plunker">
<body ng-controller="MainController as main">
<div ng-show="main.data.document.is_provided">visible</div>
<button ng-click="main.hide()">Hide</button>
<script data-require="angular.js@1.4.x"
src="https://code.angularjs.org/1.4.1/angular.js"
data-semver="1.4.1"></script>
<script src="app.js"></script>
</body>
</html>
<强> app.js 强>
angular
.module('plunker', [])
.controller('MainController', MainController);
function MainController() {
var main = this;
this.data = {
document: {
is_provided: true
}
};
this.hide = hide;
function hide() {
main.data.document.is_provided = false;
}
}
ng-click
内部存在一个问题,因为应该有函数执行。您还使用ng-if
代替ng-show
。
答案 3 :(得分:2)
处理此类问题的最佳方式(imho):
在您的视图中使用{{ anyObject | json }}
!
通过这种方式,您可以了解您正在使用的引用以及对象是否存在于您的范围中。使用| json
会在您的对象存在但空白时为您提供荣誉{}
。如果您的对象在您的范围内不可用注意,则打印&#39;。
在您的情况下,将body标签更改为:
<body ng-controller="MainCtrl as mainCtrl">
然后,在此控制器的html内添加:
DATA: {{mainCtrl | json}}
所以现在你看到你的变量了!而且你也看到点击按钮并没有改变布尔变量。
通过一些额外的调试和重写,这可行:
app.controller('MainCtrl', function($scope) {
var main = this;
this.data = {
document: {
is_provided: true
}
};
$scope.hide = function() {
console.log(main);
main.data.document.is_provided = !main.data.document.is_provided;
}
});
和:
<button ng-click="hide()">Hide</button>
(注意括号)