Reputation: 1273
I'm using the controllerAs syntax, and for some reason, when updating a controller's field in an $interval, it doesn't show/hide elements in the view properly. I use angular's UI router.
The issue is best described with code I think, so please forgive the code dump.
My state (the "refreshLogs" simply is a function to call the logService for an updated log):
angular.module('portal')
.config(function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('logs', {
'abstract': true,
views: {
"@": { template: '<div ui-view></div>' }
}
})
.state('logs.view', {
url: '/logs/:id',
resolve: {
log: function ($stateParams, logService) {
return logService.getLog($stateParams.id);
},
refreshLog: function ($stateParams, logService) {
var id = $stateParams.id
var fn = function (id) {
return logService.getLog(id)
};
return function() { return fn(id) }
}
},
templateUrl: '/app/logs/viewlog.html',
controller: 'logController',
controllerAs: 'vm'
})
});
My controller:
angular.module('portal.controllers')
.controller('logController', function ($state, log, refreshLog, $scope, $interval) {
var vm = this;
vm.log = log;
vm.refreshTimer = $interval(function () {
refreshLog().then(function (data) {
vm.log = data;
})
}, 15000);
$scope.$on("$destroy", function () {
if (angular.isDefined(vm.refreshTimer)) {
$interval.cancel(vm.refreshTimer);
}
});
});
And finally the view:
<div ng-show="{{ vm.log != null }}">
<div class="page-header">
<h1>{{ vm.log.JobType }} ({{ vm.log.JobResult }})</h1>
</div>
Parameters: {{ vm.log.JobParameters }}
<pre>{{ vm.log.Content }}</pre>
</div>
<div ng-show="{{ vm.log == null }}">
<div class="page-header">
<h1>Waiting for log...</h1>
</div>
</div>
It appears the "ng-show" value in the DOM updates, but the elements are NOT shown/hidden based on this value. I inspected the DOM in Chrome, and I see this (asterisks added for emphasis):
<div ui-view="" class="ng-scope"><div ng-show="**false**" class="ng-binding ng-scope ng-hide">
<div class="page-header">
<h1 class="ng-binding"> ()</h1>
</div>
Parameters:
<pre class="ng-binding"></pre>
</div>
<div ng-show="**true**" class="ng-scope">
<div class="page-header">
<h1>Waiting for log...</h1>
</div>
</div></div>
Which is correct to start with, and the proper divs are shown. After a few seconds, the log is refreshed, and the "vm.log" variable is set to a non-null value (I know this because I set a breakpoint in the JS code assigning this value, and it looks correct). Afterwards, I inspect the DOM again and see this:
<div ui-view="" class="ng-scope"><div ng-show="**true**" class="ng-binding ng-scope ng-hide">
<div class="page-header">
<h1 class="ng-binding">...</h1>
</div>
...
</pre>
</div>
<div ng-show="**false**" class="ng-scope">
<div class="page-header">
<h1>Waiting for log...</h1>
</div>
</div></div>
Notice the "ng-show" attributes showing the correct values. So, the expression has obviously been re-evaluated. However, the old "Waiting for log..." header still shows, and the first div is NOT shown (and it still has the "ng-hide" css class applied).
What am I missing here?
Upvotes: 2
Views: 444
Reputation: 1273
As Ranjith S pointed out in the comment, the issue was in the ng-show
binding!
There should be no {{ ... }}
s in there. Removing the brackets solved the issue.
Upvotes: 1