Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

ngIf and ngShow mistreats "[]" (empty array) #3969

Closed
jrencz opened this issue Sep 11, 2013 · 8 comments
Closed

ngIf and ngShow mistreats "[]" (empty array) #3969

jrencz opened this issue Sep 11, 2013 · 8 comments
Assignees
Milestone

Comments

@jrencz
Copy link

jrencz commented Sep 11, 2013

If ngIf/ngShow if given an argument of a string of 2 characters: "[" and "]" it is treated as if it would be [] - empty array, which is neither true nor false.

Here's a test (utilizing ngIf only)
http://jsfiddle.net/VeJfM/1/

@petebacondarwin
Copy link
Contributor

I am not sure I agree with this. From my chrome console:

[] == true
false

[] != true
true

(![]) == true
false

[''] == true
false

(!['']) == true
false

"" == true
false

"[]" == true
false

(!"[]") == true
false

@petebacondarwin
Copy link
Contributor

OK, I think I see what you are saying. So it seems like a design choice. See https://github.com/angular/angular.js/blob/master/src/Angular.js#L838

@mgol
Copy link
Member

mgol commented Sep 11, 2013

@petebacondarwin. ngIf and ngShow don't compare expression being equal in the sense of == to true but them being truthy; otherwise you couldn't pass references to objects to them.

From the following two examples the first will log 'a', the second: 'b':

if ('[]') {
    console.log('a');
} else {
    console.log('b');
}
if ([]) {
    console.log('a');
} else {
    console.log('b');
}

@jrencz
Copy link
Author

jrencz commented Sep 11, 2013

@petebacondarwin: you're right, and it's like that for more than 3 years now in https://github.com/angular/angular.js/blob/a7d62dcb5533ceb9a7ae47ee27e2054400a0196b/src/Angular.js

But if it's by design should it return nothing? Shouldn't it trigger some kind of error informing developer to pass custom function implementing logic and returning either true or false?
The case of "[]" and [] is unsolvable since there's no ngIfNot like there's ngHide for ngShow

@mgol
Copy link
Member

mgol commented Sep 11, 2013

@petebacondarwin It seems illogical that ng-if can return false on both !x and x. This kind of interpolation is also inconsistent with the rest of JavaScript and even internally with Angular expressions, e.g. ng-if="'[]'" evaluates to false and an element is hidden but {{ '[]' ? 'a' : 'b' }} and {{ [] ? 'a' : 'b' }} both print 'a' which means an empty array (as well as the string '[]') is truthy in this case. Why not just be consistent with JS?

Our use case is that we download a JSON from the server with some fields populated with user data. One of these fields should trigger showing a particular element only if the user actually wrote anything in that field (i.e. it's a non-empty string). But one of the things user can write is [], obviously which makes the element hide. This also seems unexpected as we didn't expect a string from the server to be parsed against some kinds of expressions.

@IgorMinar
Copy link
Contributor

v == '[]' in https://github.com/angular/angular.js/blob/master/src/Angular.js#L838 is wrong.

the javascript truthiness type coercion is crazy too though. (all of these are falsy: [], [0], [false], [''])

@mgol
Copy link
Member

mgol commented Sep 14, 2013

@IgorMinar That's not true, everything you mentioned is truthy... As is every object, even ones without any keys.
The most common falsey values are false, null, undefined, 0 and "" and that's about it.

JS has some crazy coercion rules so to be clear, the value x is truthy if and only if !!x is true, falsey otherwise. x being truthy is equivalent to the following code printing 'a' to the console:

if (x) {
    console.log('a');
} else {
    console.log('b');
}

lgalfaso added a commit to lgalfaso/angular.js that referenced this issue Sep 15, 2013
Make ng-if evaluate things using javascript logic
Do not reevaluate everything contained within an ng-if when there
is a change of the value of the ng-if, but the truthy of falsy value
does not change

Fixes angular#3969

BREAKING CHANGE: The expressions
* `<div ng-if="[]">X</div>`
* `<div ng-if="'f'">X</div>`
* `<div ng-if="'[]'">X</div>`

used to be evaluated to `false`
@megamaddu
Copy link

Is this resolved? All the boolean angular expressions I've seen are using angular's toBoolean method, which treats empty arrays as falsy. I agree with @mzgol, it doesn't make any sense to allow JavaScript boolean logic inside an expression and then evaluate the result using something completely different. "[]" -> false, "![]" -> false (what!?), "!![]" -> true (makes sense, but then you'd expect "[]" to be truthy too)

lgalfaso added a commit to lgalfaso/angular.js that referenced this issue Feb 5, 2014
Make ngShow and ngHide follow javascript `truthy`/`falsy` logic and
not the custom toBoolean logic

Fixes angular#5414 angular#4277 angular#3969

BREAKING CHANGE: The expressions

* `<div ng-hide="[]">X</div>`
* `<div ng-hide="'f'">X</div>`
* `<div ng-hide="'[]'">X</div>`

used to be evaluated to `false` and the elements were hidden.

The same effect is present for `ng-show` and the elements are now
  visible; and with `ng-if` and the elements are now removed

If you were previously doing `ng-show="exp"` where
  `$scope.exp = 'no' // (or 'n' or 'f')`, then instead write
  `ng-show="exp && exp !== 'no'` (or 'n' or 'f').
lgalfaso added a commit to lgalfaso/angular.js that referenced this issue Feb 5, 2014
Make ngIf, ngShow and ngHide follow javascript `truthy`/`falsy`
logic and not the custom toBoolean logic

Fixes angular#5414 angular#4277 angular#3969

BREAKING CHANGE: The expressions

* `<div ng-hide="[]">X</div>`
* `<div ng-hide="'f'">X</div>`
* `<div ng-hide="'[]'">X</div>`

used to be evaluated to `false` and the elements were hidden.

The same effect is present for `ng-show` and the elements are now
  visible; and with `ng-if` and the elements are now removed

If you were previously doing `ng-show="exp"` where
  `$scope.exp = 'no' // (or 'n' or 'f')`, then instead write
  `ng-show="exp && exp !== 'no'` (or 'n' or 'f').
lgalfaso added a commit to lgalfaso/angular.js that referenced this issue Jun 5, 2014
Make ngIf, ngShow and ngHide follow javascript `truthy`/`falsy`
logic and not the custom toBoolean logic

Fixes angular#5414 angular#4277 angular#3969

BREAKING CHANGE: The expressions

* `<div ng-hide="[]">X</div>`
* `<div ng-hide="'f'">X</div>`
* `<div ng-hide="'[]'">X</div>`

used to be evaluated to `false` and the elements were hidden.

The same effect is present for `ng-show` and the elements are now
  visible; and with `ng-if` and the elements are now removed

If you were previously doing `ng-show="exp"` where
  `$scope.exp = 'no' // (or 'n' or 'f')`, then instead write
  `ng-show="exp && exp !== 'no'` (or 'n' or 'f').
@IgorMinar IgorMinar modified the milestones: 1.3.0-beta.14, Backlog Jun 22, 2014
mgol added a commit to mgol/angular.js that referenced this issue Jun 23, 2014
So far Angular have used the toBoolean function to decide if the parsed value
is truthy. The function made more values falsy than regular JavaScript would,
e.g. strings 'f' and 'no' were both treated as falsy. This creates suble bugs
when backend sends a non-empty string with one of these values and something
suddenly hides in the application

BREAKING CHANGE: values 'f', '0', 'false', 'no', 'n', '[]' are no longer
treated as falsy; only JavaScript falsy values are treated as falsy by the
expression parser; there are six of them: false, null, undefined, NaN, o and "".

Fixes angular#3969
Fixes angular#4277
mgol added a commit to mgol/angular.js that referenced this issue Jun 23, 2014
So far Angular have used the toBoolean function to decide if the parsed value
is truthy. The function made more values falsy than regular JavaScript would,
e.g. strings 'f' and 'no' were both treated as falsy. This creates suble bugs
when backend sends a non-empty string with one of these values and something
suddenly hides in the application

BREAKING CHANGE: values 'f', '0', 'false', 'no', 'n', '[]' are no longer
treated as falsy. Only JavaScript falsy values are now treated as falsy by the
expression parser; there are six of them: false, null, undefined, NaN, o and "".

Fixes angular#3969
Fixes angular#4277
mgol added a commit to mgol/angular.js that referenced this issue Jun 23, 2014
So far Angular have used the toBoolean function to decide if the parsed value
is truthy. The function made more values falsy than regular JavaScript would,
e.g. strings 'f' and 'no' were both treated as falsy. This creates suble bugs
when backend sends a non-empty string with one of these values and something
suddenly hides in the application

BREAKING CHANGE: values 'f', '0', 'false', 'no', 'n', '[]' are no longer
treated as falsy. Only JavaScript falsy values are now treated as falsy by the
expression parser; there are six of them: false, null, undefined, NaN, o and "".

Fixes angular#3969
Fixes angular#4277
mgol added a commit to mgol/angular.js that referenced this issue Jun 23, 2014
So far Angular have used the toBoolean function to decide if the parsed value
is truthy. The function made more values falsy than regular JavaScript would,
e.g. strings 'f' and 'no' were both treated as falsy. This creates suble bugs
when backend sends a non-empty string with one of these values and something
suddenly hides in the application

BREAKING CHANGE: values 'f', '0', 'false', 'no', 'n', '[]' are no longer
treated as falsy. Only JavaScript falsy values are now treated as falsy by the
expression parser; there are six of them: false, null, undefined, NaN, 0 and "".

Fixes angular#3969
Fixes angular#4277
mgol added a commit to mgol/angular.js that referenced this issue Jun 24, 2014
So far Angular have used the toBoolean function to decide if the parsed value
is truthy. The function made more values falsy than regular JavaScript would,
e.g. strings 'f' and 'no' were both treated as falsy. This creates suble bugs
when backend sends a non-empty string with one of these values and something
suddenly hides in the application

Thanks to lgalfaso for test ideas.

BREAKING CHANGE: values 'f', '0', 'false', 'no', 'n', '[]' are no longer
treated as falsy. Only JavaScript falsy values are now treated as falsy by the
expression parser; there are six of them: false, null, undefined, NaN, 0 and "".

Fixes angular#3969
Fixes angular#4277
mgol added a commit to mgol/angular.js that referenced this issue Jun 24, 2014
So far Angular have used the toBoolean function to decide if the parsed value
is truthy. The function made more values falsy than regular JavaScript would,
e.g. strings 'f' and 'no' were both treated as falsy. This creates suble bugs
when backend sends a non-empty string with one of these values and something
suddenly hides in the application

Thanks to lgalfaso for test ideas.

BREAKING CHANGE: values 'f', '0', 'false', 'no', 'n', '[]' are no longer
treated as falsy. Only JavaScript falsy values are now treated as falsy by the
expression parser; there are six of them: false, null, undefined, NaN, 0 and "".

Fixes angular#3969
Fixes angular#4277
mgol added a commit to mgol/angular.js that referenced this issue Jun 25, 2014
So far Angular have used the toBoolean function to decide if the parsed value
is truthy. The function made more values falsy than regular JavaScript would,
e.g. strings 'f' and 'no' were both treated as falsy. This creates suble bugs
when backend sends a non-empty string with one of these values and something
suddenly hides in the application

Thanks to lgalfaso for test ideas.

BREAKING CHANGE: values 'f', '0', 'false', 'no', 'n', '[]' are no longer
treated as falsy. Only JavaScript falsy values are now treated as falsy by the
expression parser; there are six of them: false, null, undefined, NaN, 0 and "".

Fixes angular#3969
Fixes angular#4277
@mgol mgol closed this as completed in bdfc9c0 Jun 26, 2014
ckknight pushed a commit to ckknight/angular.js that referenced this issue Jul 16, 2014
So far Angular have used the toBoolean function to decide if the parsed value
is truthy. The function made more values falsy than regular JavaScript would,
e.g. strings 'f' and 'no' were both treated as falsy. This creates suble bugs
when backend sends a non-empty string with one of these values and something
suddenly hides in the application

Thanks to lgalfaso for test ideas.

BREAKING CHANGE: values 'f', '0', 'false', 'no', 'n', '[]' are no longer
treated as falsy. Only JavaScript falsy values are now treated as falsy by the
expression parser; there are six of them: false, null, undefined, NaN, 0 and "".

Closes angular#3969
Closes angular#4277
Closes angular#7960
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
5 participants