Let's say in the condition of AngularJS's ngShow
, what if a property doesn't exist?
For example, if vm.foo
is 1
, then what if in the HTML, there is a
<div ng-show="myCtrl.foo.bar.wa.la">
hello
</div>
and what if it is
<div ng-show="!myCtrl.foo.bar.wa.la">
hello
</div>
Example at: https://jsfiddle.net/4yg2ocy6/1/
(If it is pure JavaScript, it will raise an exception)
I suspect that
myCtrl.foo.bar.wa.la
is treated by AngularJS as the same as:
(myCtrl.foo && myCtrl.foo.bar && myCtrl.foo.bar.wa && myCtrl.foo.bar.wa.la)
and
!myCtrl.foo.bar.wa.la
is the same as
!(myCtrl.foo && myCtrl.foo.bar && myCtrl.foo.bar.wa && myCtrl.foo.bar.wa.la)
but I can't find any documentation about it.
Another possibility is that it treats (myCtrl.foo.bar.wa.la)
as one unit, if Angular can evaluate it, then return the result, but if it raises an exception, catch it and return false. So for !myCtrl.foo.bar.wa.la
, it will treat it as !false
and therefore is true
.
Is there a more definite spec for this?
The short (and sweet) answer
myCtrl.foo.bar.wa.la
will evaluate to undefined
which doesn't trigger ngShow
.
The long answer
One important thing to note from Angular Expressions vs. JavaScript Expressions:
Forgiving: In JavaScript, trying to evaluate undefined properties generates ReferenceError or TypeError. In Angular, expression evaluation is forgiving to undefined and null.
This means that something like a.very.long.reference.which.does.not.exist
won't throw an error and will evaluate to undefined. See this example:
angular
.module('myApp', [])
.controller('MainCtrl', function() {
var vm = this;
vm.typeOf = function(value) {
return typeof value;
};
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.3/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="MainCtrl as vm">
<div>{{ vm.typeOf(a.very.long.reference.which.does.not.exist) }}</div>
</div>
</div>
Now, to answer your questions. Internally, both ngHide and ngShow, use a basic check to see if the expression is true or not. They do something like: if (expression) { // do this } else { // do that }
.
Since both ngHide
and ngShow
are triggered when the expression
is truthy, and that a.very.long.reference.which.does.not.exist
evaluates to undefined
, is clear to see why they aren't triggered when a property doesn't exist.
Some expressions and their evaluation:
undefined ? 'truthy' : 'falsy' // 'falsy'
null ? 'truthy' : 'falsy' // 'falsy'
// Booleans
true ? 'truthy' : 'falsy' // 'truthy'
false ? 'truthy' : 'falsy' // 'falsy'
// Numbers
1 ? 'truthy' : 'falsy' // 'truthy'
0 ? 'truthy' : 'falsy' // 'falsy'
0.00001 ? 'truthy' : 'falsy' // 'truthy'
NaN ? 'truthy' : 'falsy' // 'falsy'
// Strings
'something' ? 'truthy' : 'falsy' // 'truthy'
'0' ? 'truthy' : 'falsy' // 'truthy'
'' ? 'truthy' : 'falsy' // 'falsy'
({}) ? 'truthy' : 'falsy' // 'truthy'
[] ? 'truthy' : 'falsy' // 'truthy'
(new Date()) ? 'truthy' : 'falsy' // 'truthy'