I am trying to bind to a boolean variable on my controller's scope to indicate whether or not a loading animation should be displayed. However, the following code does not work. The function inside $timeout
runs, but the view is not updated.
When I inspect the scope using the chrome angular extension, I see that ctrl.loading
is true
.
Is this because of booleans being value types in javascript, as opposed to reference types?
My guess is that the view is literally binding to true
, and not to the location of a boolean value which would change.
How do I get the view to bind to the variable, and not to the value, the variable has initially?
controller:
function TestController($scope,$timeout){
"use strict";
var loading=true;
$timeout(function(){
loading=false;
}, 1000);
return {
loading:loading
}
}
template:
<div>
<h1 ng-show="ctrl.loading">Loading</h1>
<h1 ng-hide="ctrl.loading">Not Loading</h1>
</div>
The abovecode is just an example, really I would set the value after a get request wqas returned.
$http.get().then(function() {
loading=false;
}, function() {
loading=false;
})
but the effect is the same.
You are binding the loading
variable wrongly. You either need to register that variable loading
to the $scope
or to the this
variable. See the below working example:
var app = angular.module("sa", []);
app.controller("TestController", TestController);
function TestController($scope, $timeout) {
"use strict";
var vm = this;
vm.loading = true;
$timeout(function() {
vm.loading = false;
}, 2000);
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="sa" ng-controller="TestController as ctrl">
<h1 ng-show="ctrl.loading">Loading</h1>
<h1 ng-hide="ctrl.loading">Not Loading</h1>
</div>
Also, the return block in the controller is of no use.
Edit
Now, I understand your question. This is the first time I saw this feature of returning from the controller. After half an hour of researching, I found out that you can't expect a primitive type to be passed by reference in Javascript. You need to use some object.
See the scope inheritance problem to get a gist: https://github.com/angular/angular.js/wiki/Understanding-Scopes
To fix this, you can alter your code like below:
var app = angular.module("sa", []);
app.controller("TestController", TestController);
function TestController($scope, $timeout) {
"use strict";
var myData = {};
myData.loading = true;
$timeout(function() {
myData.loading = false;
}, 2000);
return {
myData: myData
};
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="sa" ng-controller="TestController as ctrl">
<h1 ng-show="ctrl.myData.loading">Loading</h1>
<h1 ng-hide="ctrl.myData.loading">Not Loading</h1>
</div>