I have no problem getting ng-show to work when I use a scoped variable:
(excerpt from html file:)
<li ng-show="hasBattery">
<span>Battery</span>
<dl>
<dt>Type</dt>
<dd>{{phone.battery.type}}</dd>
</dl>
</li>
using the following controller code, which works fine:
phonecatControllers.controller('PhoneDetailCtrl', ['$scope', '$routeParams', '$http',
function($scope, $routeParams, $http) {
function loadData() {
// fyi, the ?date nonsense below is to avoid browser cacheing of the json file
$http.get('phones/' + $routeParams.phoneId + '.json' + '?' +
new Date().getTime()).success(function(data) {
$scope.phone = data;
$scope.hasBattery = !$scope.isEmpty($scope.phone.battery.type);
// should i call some form of $scope.$apply() here? when i do,
// i get a digest already in progress error. ng-show seems to
// update fine without a call to $apply
});
};
$scope.isEmpty = function(str) {
var retVal = (typeof(str) === undefined || !str || 0 === str.length);
alert("isempty: returning " + retVal);
return retVal;
};
$scope.hasBattery = false;
loadData();
}
]);
Like I said, that works. When I view a page whose phone.battery.type is undefined or blank, ng-show correctly hides the div. When I view a page whose phone.battery.type is a non-empty string, ng-show correctly shows the div. All good.
Here's my question: when I use the !isEmpty(...) call directly in the ng-show expression, instead of using $scope.hasBattery as an intermediary, it doesn't work.
Here's my code for that version:
<li ng-show="{{!isEmpty(phone.battery.type)}}">
<span>Battery</span>
<dl>
<dt>Type</dt>
<dd>{{phone.battery.type}}</dd>
</dl>
</li>
controller, with hasBattery removed:
phonecatControllers.controller('PhoneDetailCtrl', ['$scope', '$routeParams', '$http',
function($scope, $routeParams, $http) {
function loadData() {
$http.get('phones/' + $routeParams.phoneId + '.json' + '?' + new Date().getTime()).success(function(data) {
$scope.phone = data;
// no longer do any evaluation of isEmpty here.
// as before, I'm not calling $scope.$apply() at all
});
};
// same code as before
$scope.isEmpty = function(str) {
var retVal = (typeof(str) === undefined || !str || 0 === str.length);
alert("isempty: returning " + retVal);
return retVal;
};
loadData();
}
]);
When I load a page whose phone.battery.type is a non-empty string, which I want ng-show to show, it fails to show the div. I see that isEmpty is indeed being called after the data loads, and is correctly returning false (so that ng-show's expression, !isEmpty(...), is true). But it seems like Angular is not doing anything with the value of this expression!
.
Any idea what's going on? I would think this was a $scope.$apply problem, like I've seen elsewhere on SO, but the expression does seem to be being evaluated using up to date data.