Exemple rapide:
Il existe un paramètre routé (/ Home /: isLoggedIn) qui correspond à true ou à false. (/ Demo/#/Home/false) et une propriété de contrôleur
this.loggedIn = this.routeParams.loggedIn;
J'ai une vue (Home.html) qui a deux éléments, chacun avec un attribut ng-if.
<div ng-if="home.loggedIn">
Logged In!
</div>
<div ng-if="!home.loggedIn">
Not Logged In...
</div>
Si je navigue dans/Demo/#/Home/true, le premier élément s'affiche alors que le second ne le fait pas .. Si je navigue dans/Demo/#/Home/false, le premier élément ne s'affiche pas NOR fait le deuxième.
Je m'attendrais à ce que le paramètre! Home.loggedIn soit évalué à true lorsque la valeur de LogIn est, en fait, false.
Un conseil ici?
Il est évident que le problème tient au fait que routeParams.loggedIn
est une chaîne.
La solution est donc évidente:
// Change that:
this.loggedIn = this.routeParams.loggedIn;
// To this:
this.loggedIn = this.routeParams.loggedIn === 'true';
Mais pourquoi ce comportement étrange?
Pourquoi ne rien montrer quand loggedIn
est 'faux'?
Eh bien, voici pourquoi:
La directive ngIf
utilise la fonction toBoolean()
suivante pour convertir sa valeur en booléen:
function toBoolean(value) {
if (typeof value === 'function') {
value = true;
} else if (value && value.length !== 0) {
var v = lowercase("" + value);
value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');
} else {
value = false;
}
return value;
}
Si une chaîne est passée à toBoolean()
, il la convertit en minuscule et vérifie (entre autres) si elle est égale à 'false' (auquel cas, elle renvoie false
). Ceci est différent de l'implémentation JavaScript par défaut qui interprète toute chaîne non vide comme true
lors de la conversion en boolean.
Alors, examinons les deux cas pour les deux ngIf
s:
loggedIn === 'true'
ngIf1 évalue home.loggedIn
-> 'true' (chaîne)
ngIf1 transmet cette valeur à toBoolean()
toBoolean('true')
renvoie true (car il voit une chaîne qui ne peut correspondre à aucune chaîne considérée comme falsy)
ngIf1 rend son contenu
ngIf2 évalue !home.loggedIn
<=> !'true'
-> false (booléen)
(cela se produit car toute chaîne non vide doit être évaluée comme étant vraie)
ngIf2 transmet cette valeur à toBoolean()
toBoolean(false)
renvoie false
ngIf2 ne rend pas son contenu
loggedIn === 'false'
ngIf1 évalue home.loggedIn
-> 'false' (chaîne)
ngIf1 transmet cette valeur à toBoolean()
toBoolean('false')
renvoie false (car il voit une chaîne considérée comme falsy
ngIf1 ne rend pas son contenu
ngIf2 évalue !home.loggedIn
<=> !'false'
-> false (booléen)
(cela se produit car toute chaîne non vide doit être évaluée comme étant vraie)
ngIf2 transmet cette valeur à toBoolean()
toBoolean(false)
renvoie false
ngIf2 ne rend pas son contenu
Donc, cela explique le comportement "étrange" (de manière compréhensible, espérons-le).
Le problème est probable home.loggedIn est une chaîne, lorsqu'elle est transmise à ng, si elle évalue et effectue probablement la conversion de chaîne en bool pour obtenir la valeur "false" en false. Dans l'évaluation de l'expression avant que la valeur ne soit passée, si vous avez! "False", cela est en réalité faux puisque toute chaîne est vraie, la négation devient fausse.