Quelle est la différence entre ng-if et ng-show / ng-hide

427

J'essaie de comprendre la différence entre ng-ifet ng-show/ ng-hide, mais ils me semblent identiques.

Y a-t-il une différence que je dois garder à l'esprit en choisissant d'utiliser l'un ou l'autre?

Stéphane Rolland
la source

Réponses:

521

ngIf

La ngIfdirective supprime ou recrée une partie de l'arborescence DOM en fonction d'une expression. Si l'expression affectée à ngIfévalue une valeur fausse, l'élément est supprimé du DOM, sinon un clone de l'élément est réinséré dans le DOM.

<!-- when $scope.myValue is truthy (element is restored) -->
<div ng-if="1"></div>

<!-- when $scope.myValue is falsy (element is removed) -->
<div ng-if="0"></div>

Lorsqu'un élément est supprimé à l'aide de ngIfsa portée, il est détruit et une nouvelle portée est créée lors de la restauration de l'élément. La portée créée dans ngIfhérite de sa portée parent à l'aide de l'héritage prototypique.

Si ngModelest utilisé dans ngIfpour se lier à une primitive JavaScript définie dans la portée parent, toute modification apportée à la variable dans la portée enfant n'affectera pas la valeur dans la portée parent, par exemple

<input type="text" ng-model="data">
<div ng-if="true">
    <input type="text" ng-model="data">
</div>        

Pour contourner cette situation et mettre à jour le modèle dans la portée parent depuis l'intérieur de la portée enfant, utilisez un objet:

<input type="text" ng-model="data.input">
<div ng-if="true">
    <input type="text" ng-model="data.input">
</div>

Ou, $parentvariable pour référencer l'objet de portée parent:

<input type="text" ng-model="data">
<div ng-if="true">
    <input type="text" ng-model="$parent.data">
</div>

ngShow

La ngShowdirective affiche ou masque l'élément HTML donné en fonction de l'expression fournie à l' ngShowattribut. L'élément est affiché ou masqué en supprimant ou en ajoutant la ng-hideclasse CSS à l'élément. La .ng-hideclasse CSS est prédéfinie dans AngularJS et définit le style d'affichage sur aucun (à l'aide d'un !importantindicateur).

<!-- when $scope.myValue is truthy (element is visible) -->
<div ng-show="1"></div>

<!-- when $scope.myValue is falsy (element is hidden) -->
<div ng-show="0" class="ng-hide"></div>

Lorsque l' ngShowexpression est évaluée, falsela ng-hideclasse CSS est ajoutée à l' classattribut de l'élément, ce qui le rend masqué. Lorsque true, la ng-hideclasse CSS est supprimée de l'élément, ce qui ne semble pas masqué.

AlwaysALearner
la source
31
Astuce: En supprimant l'élément HTML lui-même avec ng-ifle modèle, ajouté par ng-model, n'existe plus.
mrzmyr
3
@CodeHater J'ai réussi à exploiter ng-if sur ng-show / ng-hide sur une page qui aurait autrement eu un grand dom. Il semblait faire la page se sentir plus vite, mais nullement d'analyse scientifique.
Ed Spencer
La partie que j'ai du mal à bien comprendre est comment / pourquoi quand vous avez un objet dans le modèle, data.inputcela fonctionne ... mais dataseul dans le modèle ne fonctionne pas. @CodeHater
Mark Pieszak - Trilon.io
7
@mcpDESIGNS ngIfcrée une nouvelle étendue, donc en regardant l'exemple ci-dessus l'imbriqué ngModelcréerait un nouveau datamodèle même si un modèle du même nom existe dans l'étendue parent. Mais lorsque vous utilisez une notation par points, vous demandez à JS de rechercher la chaîne de prototypes de l'oscilloscope. Donc, s'il ne trouve pas la valeur dans la portée actuelle, il essaiera de la rechercher dans la portée parent et ainsi de suite. Peu d' autres directives qui créent une portée différente sont ngInclude, ngRepeat. J'espère que c'est clair maintenant. :)
AlwaysALearner
3
Lequel est le meilleur pour la performance? Je pense que ng-show et ng-hide n'est-ce pas?
tom10271
97

Peut-être un point intéressant à faire est la différence entre les priorités entre les deux.

Pour autant que je sache, la directive ng-if a l'une des priorités les plus élevées (sinon la plus élevée) de toutes les directives angulaires. Ce qui signifie: il s'exécutera en PREMIER avant toutes les autres directives, de moindre priorité. Le fait qu'il s'exécute en PREMIER signifie que l'élément est supprimé avant le traitement des directives internes . Ou du moins: c'est ce que j'en fais.

J'ai observé et utilisé cela dans l'interface utilisateur que je construis pour mon client actuel. L'interface utilisateur entière est assez compacte, et il y avait ng-show et ng-hide partout. Pour ne pas entrer dans trop de détails, mais j'ai construit un composant générique, qui pourrait être géré à l'aide de la configuration JSON, j'ai donc dû faire quelques changements à l'intérieur du modèle. Il y a un ng-repeat présent, et à l'intérieur du ng-repeat, un tableau est affiché, qui a beaucoup de ng-shows, ng-hides et même ng-switches présents. Ils voulaient afficher au moins 50 répétitions dans la liste, ce qui entraînerait la résolution de plus ou moins 1500-2000 directives. J'ai vérifié le code, et le backend Java + JS personnalisé sur le front prendrait environ 150 ms pour traiter les données, puis Angular mâcherait environ 2-3 secondes dessus, avant de s'afficher. Le client ne s'est pas plaint, mais j'ai été consterné :-)

Dans ma recherche, je suis tombé sur la directive ng-if. Maintenant, il vaut peut-être mieux souligner qu'au moment de concevoir cette interface utilisateur, il n'y avait pas de ng-if disponible. Parce que le ng-show et le ng-hide avaient des fonctions en eux, qui renvoyaient des booléens, je pouvais facilement les remplacer tous par ng-if. Ce faisant, toutes les directives internes ne semblaient plus être évaluées. Cela signifiait que je suis revenu à environ un tiers de toutes les directives en cours d'évaluation, et donc, l'interface utilisateur a accéléré jusqu'à environ 500 ms - 1 seconde de temps de chargement. (Je n'ai aucun moyen de déterminer les secondes exactes)

Remarque: le fait que les directives ne soient pas évaluées est une supposition éclairée de ce qui se passe en dessous.

Donc, à mon avis: si vous avez besoin que l'élément soit présent sur la page (c'est-à-dire: pour vérifier l'élément, ou autre), mais simplement être caché, utilisez ng-show / ng-hide. Dans tous les autres cas, utilisez ng-if.

gjoris
la source
1
Oui, je suppose que c'est l'objectif de ng-if: réduire le temps de traitement. Cette directive existe à coup sûr non seulement à cause de certains pseudosélecteurs CSS. Bon post! +1
Bartłomiej Zalewski
36

La ng-ifdirective supprime le contenu de la page et ng-show/ng-hideutilise la displaypropriété CSS pour masquer le contenu.

Ceci est utile dans le cas où vous souhaitez utiliser :first-childet :last-childsélecteurs de pseudo au style.

Andrei
la source
que voulez-vous dire en utilisant les sélecteurs: premier et: dernier?
Stephane Rolland
16

@EdSpencer est correct. Si vous avez beaucoup d'éléments et que vous utilisez ng-if pour instancier uniquement les éléments pertinents, vous économisez des ressources. @CodeHater est également quelque peu correct, si vous souhaitez supprimer et afficher un élément très souvent, le cacher au lieu de le supprimer pourrait améliorer les performances.

Le principal cas d'utilisation que je trouve pour ng-if est qu'il me permet de valider et d'éliminer proprement un élément si le contenu est illégal. Par exemple, je pourrais faire référence à une variable de nom d'image nulle et cela générera une erreur, mais si je négocie et vérifie si elle est nulle, tout va bien. Si je faisais un ng-show, l'erreur se déclencherait toujours.

AturSams
la source
7

Une chose importante à noter à propos de ng-if et ng-show est que lorsque vous utilisez des contrôles de formulaire, il est préférable d'utiliser ng-if car il supprime complètement l'élément du dom.

Cette différence est importante car si vous créez un champ de saisie avec required="true"puis définissez-le ng-show="false"pour le masquer, Chrome générera l'erreur suivante lorsque l'utilisateur tentera de soumettre le formulaire:

An invalid form control with name='' is not focusable.

La raison étant que le champ de saisie est présent et il l'est requiredmais puisqu'il est caché, Chrome ne peut pas se concentrer dessus. Cela peut littéralement casser votre code car cette erreur arrête l'exécution du script. Donc sois prudent!

supersan
la source
C'est le fait réel, si vous utilisez des contrôles de formulaire pour la validation, vous souffrirez beaucoup si vous utilisez ng-show / ng-hide. Et si vous avez plusieurs sections cachées / affichées en fonction de l'expression. Donc, si vous utilisez ng-show / hide, les éléments seront toujours là et la validation échouera, bien qu'ils ne soient pas à l'écran. donc ng-si vous sauver :)
NeverGiveUp161
5

@Gajus Kuizinas et @CodeHater sont corrects. Ici, je donne juste un exemple. Pendant que nous travaillons avec ng-if, si la valeur assignée est fausse, tous les éléments html seront supprimés du DOM. et si la valeur assignée est vraie, alors les éléments html seront visibles sur le DOM. Et la portée sera différente de la portée parent. Mais en cas de ng-show, il affichera et masquera simplement les éléments en fonction de la valeur assignée. Mais il reste toujours dans le DOM. Seule la visibilité change selon la valeur attribuée.

http://plnkr.co/edit/3G0V9ivUzzc8kpLb1OQn?p=preview

J'espère que cet exemple vous aidera à comprendre les portées. Essayez de donner de fausses valeurs à ng-show et ng-if et vérifiez le DOM dans la console. Essayez d'entrer les valeurs dans les zones de saisie et observez la différence.

<!DOCTYPE html>

Bonjour Plunker!

<input type="text" ng-model="data">
<div ng-show="true">
    <br/>ng-show=true :: <br/><input type="text" ng-model="data">
</div>
<div ng-if="true">
    <br/>ng-if=true :: <br/><input type="text" ng-model="data">
</div> 
{{data}}


la source
2

En fait, cette ng-ifdirective, contrairement à elle ng-show, crée son propre champ d’application, conduit à une différence pratique intéressante:

angular.module('app', []).controller('ctrl', function($scope){
  $scope.delete = function(array, item){
    array.splice(array.indexOf(item), 1);
  }
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app='app' ng-controller='ctrl'>
   <h4>ng-if:</h4>
   <ul ng-init='arr1 = [1,2,3]'>
      <li ng-repeat='x in arr1'>
        {{show}}
        <button ng-if='!show' ng-click='show=!show'>Delete {{show}}</button>
        <button ng-if='show' ng-click='delete(arr1, x)'>Yes {{show}}</button>
        <button ng-if='show' ng-click='show=!show'>No</button>
      </li>
   </ul>
   
   <h4>ng-show:</h4>
   <ul ng-init='arr2 = [1,2,3]'>
      <li ng-repeat='x in arr2'>
        {{show}}
        <button ng-show='!show' ng-click='show=!show'>Delete {{show}}</button>
        <button ng-show='show' ng-click='delete(arr2, x)'>Yes {{show}}</button>
        <button ng-show='show' ng-click='show=!show'>No</button>
      </li>
   </ul>
   
   <h4>ng-if with $parent:</h4>
    <ul ng-init='arr3 = [1,2,3]'>
      <li ng-repeat='item in arr3'>
        {{show}}
        <button ng-if='!show' ng-click='$parent.show=!$parent.show'>Delete {{$parent.show}}</button>
        <button ng-if='show' ng-click='delete(arr3, x)'>Yes {{$parent.show}}</button>
        <button ng-if='show' ng-click='$parent.show=!$parent.show'>No</button>
      </li>
   </ul>
</div>

Dans la première liste, l' on-clickévénement, la showvariable, de portée interne / propre , est modifié, mais ng-ifsurveille une autre variable de portée externe avec le même nom, donc la solution ne fonctionne pas. Au cas où ng-shownous avons la seule showvariable, c'est pourquoi cela fonctionne. Pour corriger la première tentative, nous devons faire référence à showpartir de la portée parent / externe via $parent.show.

Slava Utesinov
la source
1
  1. ng-if if false supprimera les éléments du DOM. Cela signifie que tous vos événements, les directives attachées à ces éléments seront perdus. Par exemple, ng-cliquez sur l'un des éléments enfants, lorsque ng-if est évalué à false, cet élément sera supprimé du DOM et à nouveau lorsqu'il est vrai, il est recréé.

  2. ng-show / ng-hide ne supprime pas les éléments du DOM. Il utilise des styles CSS (.ng-hide) pour masquer / afficher les éléments. De cette façon, vos événements, les directives qui ont été attachées aux enfants ne seront pas perdus.

  3. ng-if crée une portée enfant, contrairement à ng-show / ng-hide.

Amay Kulkarni
la source
1

ng-show et ng-hide fonctionnent de manière opposée. Mais la différence entre ng-hide ou ng-show avec ng-if est, si nous utilisons ng-if, alors l'élément sera créé dans le dom mais avec ng-hide / ng-show, l'élément sera complètement masqué.

ng-show=true/ng-hide=false:
Element will be displayed

ng-show=false/ng-hide=true:
element will be hidden

ng-if =true
element will be created

ng-if= false
element will be created in the dom. 
user1001
la source
0

À noter, une chose qui m'est arrivée maintenant: ng-show masque le contenu via css, oui, mais cela a entraîné d'étranges problèmes dans les divs censés être des boutons.

J'avais une carte avec deux boutons en bas et en fonction de l'état réel, elle est échangée avec un troisième bouton d'édition d'exemple avec une nouvelle entrée. En utilisant ng-show = false pour masquer celui de gauche (présent en premier dans le fichier), il est arrivé que le bouton suivant se retrouve avec la bordure droite à l'extérieur de la carte. ng-if corrige cela en n'incluant pas du tout le code. (Juste vérifié ici s'il y a des surprises cachées en utilisant ng-if au lieu de ng-show)

helius
la source
0

ngIf effectue une manipulation sur le DOM en supprimant ou recréant l'élément.

Alors que ngShow applique des règles CSS pour masquer / afficher les choses.

Pour la plupart des cas (pas toujours) , je résumerais cela comme: si vous avez besoin d'une vérification unique pour afficher / masquer les choses, utilisez ng-if, si vous devez afficher / masquer les choses en fonction des actions de l'utilisateur à l'écran (comme vérifié une case à cocher puis afficher la zone de texte, décoché puis masquer la zone de texte, etc.), puis utiliserng-show

curiousBoy
la source
-17

Une différence intéressante entre ng-if et ng-show est:

SÉCURITÉ

Les éléments DOM présents dans le bloc ng-if ne seront pas rendus en cas de valeur false

où comme dans le cas de ng-show, l'utilisateur peut ouvrir votre fenêtre Inspect Element et définir sa valeur sur TRUE.

Et avec un whoop, tout le contenu qui devait être caché s'affiche, ce qui constitue une faille de sécurité. :)

Ashish_B
la source
27
Il s'agit d'une forme de sécurité extrêmement faible. Si le contenu est donné au client par le serveur, vous devez supposer que l'utilisateur / l'attaquant peut y accéder, qu'il soit présent ou non dans le DOM. Toute logique d'autorisation doit être appliquée par le serveur.
tlrobinson
pensez à html plutôt qu'à jsp ... maintenant si vous voulez appliquer la sécurité sur les composants html ... si vous voulez cacher certains composants à l'utilisateur ... comment y arriveriez-vous. Et que faire si votre configuration est divisée en côté serveur pour le backend et côté client pour le front end.
Ashish_B