web-dev-qa-db-fra.com

Comment annuler le paramètre pour la directive AngularJS ng-if?

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?

15
beauXjames

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 ngIfs:

  1. 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

  2. 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).

29
gkalpak

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.

1
shaunhusain