adamdport adamdport - 23 days ago 9
AngularJS Question

Why does ng-show="true" not reference $scope.true?

If I set

$scope.true = false;
, I would expect an Angular expression that references
true
to evaluate as false. Similarly, I'd expect
$scope.false = true
and
$scope.undefined = true
to yield similar results.

Atrocious naming aside, why don't these work? Where in the angular code does it determine whether or not
$scope
properties will be referenced?



var myApp = angular.module('myapp', []);

myApp.controller('myctrl', function($scope) {

$scope.foo = "bar";

$scope.true = false;
$scope.true2 = false;

$scope.false = true;
$scope.false2 = true;

$scope.undefined = true;
$scope.undefined2 = true;

});

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myapp" ng-controller="myctrl">
<p>{{ foo }}</p>
<div ng-show="true">
$scope.true is equal to false here. ng-show should hide this.
</div>
<div ng-show="true2">
$scope.true2 is equal to false here. ng-show hides this.
</div>
<div ng-hide="false">
$scope.false is equal to true here. ng-hide should hide this.
</div>
<div ng-hide="false2">
$scope.false2 is equal to true here. ng-hide hides this.
</div>
<div ng-hide="undefined">
$scope.undefined is equal to true here. ng-hide should hide this.
</div>
<div ng-hide="undefined2">
$scope.undefined2 is equal to true here. ng-hide hides this.
</div>
</div>




Answer

Only took a quick look, but this has to do with what Angular's parser considers as 'literals'. The angular parser breaks up an expression into individual tokens and builds an abstract syntax tree. Basically it does a check will be done against a mapping of literals to figure out what the token is.

  var literals = {
    'true': true,
    'false': false,
    'null': null,
    'undefined': undefined
  };

You can see more on the parser code here: https://github.com/angular/angular.js/blob/master/src/ng/parse.js

While I am not sure what you are trying to accomplish with referencing true as false (apart from confusing everyone), you should be able to customize literal values using the the parse provider: $parseProvider.addLiteral(name, value)

You could also get around this by using controller as syntax:

<div ng-controller="ctrl as vm">
...
<span ng-if="vm.false">Is shown</span>
...
</div>
...
function Ctrl() {
  this.false = true;
}