Estoy tratando de entender la diferencia entre ng-if
y ng-show
/ ng-hide
, pero me parecen iguales.
¿Hay alguna diferencia que debería tener en cuenta al elegir usar uno u otro?
Estoy tratando de entender la diferencia entre ng-if
y ng-show
/ ng-hide
, pero me parecen iguales.
¿Hay alguna diferencia que debería tener en cuenta al elegir usar uno u otro?
Respuestas:
La ngIf
directiva elimina o recrea una parte del árbol DOM en función de una expresión. Si la expresión asignada a se ngIf
evalúa como un valor falso, el elemento se elimina del DOM; de lo contrario, se vuelve a insertar un clon del elemento en el 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>
Cuando se elimina un elemento usando ngIf
su alcance, se destruye y se crea un nuevo alcance cuando se restaura el elemento. El ámbito creado dentro ngIf
hereda de su ámbito primario utilizando herencia prototípica.
Si ngModel
se usa ngIf
para enlazar a una primitiva JavaScript definida en el ámbito primario, cualquier modificación realizada a la variable dentro del ámbito secundario no afectará el valor en el ámbito primario, por ejemplo
<input type="text" ng-model="data">
<div ng-if="true">
<input type="text" ng-model="data">
</div>
Para solucionar esta situación y actualizar el modelo en el ámbito primario desde el ámbito secundario, use un objeto:
<input type="text" ng-model="data.input">
<div ng-if="true">
<input type="text" ng-model="data.input">
</div>
O, $parent
variable para hacer referencia al objeto de ámbito primario:
<input type="text" ng-model="data">
<div ng-if="true">
<input type="text" ng-model="$parent.data">
</div>
La ngShow
directiva muestra u oculta el elemento HTML dado en función de la expresión proporcionada al ngShow
atributo. El elemento se muestra u oculta eliminando o agregando la ng-hide
clase CSS en el elemento. La .ng-hide
clase CSS está predefinida en AngularJS y establece el estilo de visualización en ninguno (usando una !important
bandera).
<!-- 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>
Cuando la ngShow
expresión se evalúa false
, la ng-hide
clase CSS se agrega al class
atributo en el elemento, lo que hace que se oculte. Cuando true
, la ng-hide
clase CSS se elimina del elemento haciendo que el elemento no aparezca oculto.
data.input
funciona ... pero data
solo en el modelo no funciona. @CodeHater
ngIf
crea un nuevo ámbito, por lo que mirar el ejemplo anterior anidado ngModel
crearía un nuevo data
modelo aunque exista un modelo con el mismo nombre en el ámbito principal. Pero cuando usa una notación de puntos, hace que JS busque la cadena de prototipos del osciloscopio. Por lo tanto, si no encuentra el valor en el ámbito actual, intentará buscarlo en el ámbito primario y así sucesivamente. Algunas otras directivas que crean un ámbito diferente son ngInclude
, ngRepeat
. Espero que esté claro ahora. :)
Quizás un punto interesante es la diferencia entre las prioridades entre ambos.
Por lo que puedo decir, la directiva ng-if tiene una de las prioridades más altas (si no la más alta) de todas las directivas angulares. Lo que significa: se ejecutará PRIMERO antes que todas las demás directivas de menor prioridad. El hecho de que se ejecuta PRIMERO significa que, efectivamente, el elemento se elimina antes de que se procesen las directivas internas . O al menos: eso es lo que hago con eso.
Observé y usé esto en la interfaz de usuario que estoy construyendo para mi cliente actual. Toda la interfaz de usuario está bastante llena, y tenía ng-show y ng-hide por todas partes. No voy a entrar en demasiados detalles, pero construí un componente genérico, que podría gestionarse utilizando la configuración JSON, por lo que tuve que hacer algunos cambios dentro de la plantilla. Hay un ng-repeat presente, y dentro del ng-repeat, se muestra una tabla, que tiene muchos ng-shows, ng-hides e incluso ng-switches presentes. Querían mostrar al menos 50 repeticiones en la lista, lo que daría como resultado la resolución de más o menos 1500-2000 directivas. Verifiqué el código, y el backend de Java + JS personalizado en el frente tardaría unos 150 ms en procesar los datos, y luego Angular masticaría unos 2-3 segundos antes de mostrarlo. El cliente no se quejó, pero me horroricé :-)
En mi búsqueda, me topé con la directiva ng-if. Ahora, tal vez sea mejor señalar que al momento de concebir esta IU, no había ng-if disponible. Debido a que ng-show y ng-hide tenían funciones en ellos, que devolvieron booleanos, podría reemplazarlos fácilmente con ng-if. Al hacerlo, todas las directivas internas ya no parecían evaluadas. Eso significaba que volví a un tercio de todas las directivas que se estaban evaluando y, por lo tanto, la IU aceleró hasta aproximadamente 500 ms - 1 segundo de tiempo de carga. (No tengo forma de determinar segundos exactos)
Tenga en cuenta: el hecho de que las directivas no se evalúen, es una suposición educada sobre lo que está sucediendo debajo.
Entonces, en mi opinión: si necesita que el elemento esté presente en la página (es decir, para verificar el elemento, o lo que sea), pero simplemente estar oculto, use ng-show / ng-hide. En todos los demás casos, use ng-if.
La ng-if
directiva elimina el contenido de la página y ng-show/ng-hide
usa la display
propiedad CSS para ocultar el contenido.
Esto es útil en caso de que quiera usar :first-child
y :last-child
pseudo-selectores para estilizar.
:first-child
y :last-child
developer.mozilla.org/en-US/docs/Web/CSS/:first-child developer.mozilla.org/en-US/docs/Web/CSS/:last-child
@EdSpencer es correcto. Si tiene muchos elementos y usa ng-if solo para crear una instancia de los relevantes, está ahorrando recursos. @CodeHater también es algo correcto, si va a eliminar y mostrar un elemento muy a menudo, ocultarlo en lugar de eliminarlo podría mejorar el rendimiento.
El principal caso de uso que encuentro para ng-if es que me permite validar limpiamente y eliminar un elemento si el contenido es ilegal. Por ejemplo, podría hacer referencia a una variable de nombre de imagen nula y arrojará un error, pero si hago ng-if y compruebo si es nula, todo está bien. Si hice un ng-show, el error aún se dispararía.
Una cosa importante a tener en cuenta sobre ng-if y ng-show es que cuando se usan controles de formulario, es mejor usarlo ng-if
porque elimina completamente el elemento del dom.
Esta diferencia es importante porque si crea un campo de entrada required="true"
y luego lo configura ng-show="false"
para ocultarlo, Chrome arrojará el siguiente error cuando el usuario intente enviar el formulario:
An invalid form control with name='' is not focusable.
La razón es que el campo de entrada está presente y lo está, required
pero dado que está oculto, Chrome no puede enfocarse en él. Esto literalmente puede romper su código ya que este error detiene la ejecución del script. ¡Así que ten cuidado!
@Gajus Kuizinas y @CodeHater son correctos. Aquí solo estoy dando un ejemplo. Mientras trabajamos con ng-if, si el valor asignado es falso, todos los elementos html se eliminarán de DOM. y si el valor asignado es verdadero, los elementos html serán visibles en el DOM. Y el alcance será diferente en comparación con el alcance principal. Pero en el caso de ng-show, solo mostrará y ocultará los elementos en función del valor asignado. Pero siempre se queda en el DOM. Solo la visibilidad cambia según el valor asignado.
http://plnkr.co/edit/3G0V9ivUzzc8kpLb1OQn?p=preview
Espero que este ejemplo lo ayude a comprender los alcances. Intente dar valores falsos a ng-show y ng-if y verifique el DOM en la consola. Intente ingresar los valores en los cuadros de entrada y observe la diferencia.
<!DOCTYPE html>
<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}}
El hecho, esa ng-if
directiva, a diferencia ng-show
, crea su propio alcance, conduce a una interesante diferencia práctica:
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>
En la primera lista, el on-click
evento, la show
variable, desde el ámbito interno / propio , se cambia, pero ng-if
está observando otra variable desde el ámbito externo con el mismo nombre, por lo que la solución no funciona. En el caso de ng-show
que tengamos la única show
variable, es por eso que funciona. Para solucionar el primer intento, debemos hacer referencia a show
partir de los padres / ámbito exterior a través $parent.show
.
ng-if if false eliminará elementos del DOM. Esto significa que todos sus eventos, directivas adjuntas a esos elementos se perderán. Por ejemplo, ng-clic en uno de los elementos secundarios, cuando ng-if se evalúa como falso, ese elemento se eliminará del DOM y, de nuevo, cuando sea verdadero, se volverá a crear.
ng-show / ng-hide no elimina los elementos del DOM. Utiliza estilos CSS (.ng-hide) para ocultar / mostrar elementos. De esta manera, sus eventos, directivas que se adjuntaron a los niños no se perderán.
ng-if crea un ámbito secundario mientras que ng-show / ng-hide no lo hace.
ng-show y ng-hide funcionan de manera opuesta. Pero la diferencia entre ng-hide o ng-show con ng-if es que, si usamos ng-if, el elemento se creará en el dom pero con el elemento ng-hide / ng-show se ocultará por completo.
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.
Para tener en cuenta, algo que me sucedió ahora: ng-show oculta el contenido a través de css, sí, pero resultó en extrañas fallas en los div que se supone que son botones.
Tenía una tarjeta con dos botones en la parte inferior y, dependiendo del estado real, uno se intercambia con un tercer botón de edición de ejemplo con una nueva entrada. Usando ng-show = false para ocultar el izquierdo (presente primero en el archivo) sucedió que el siguiente botón terminó con el borde derecho fuera de la tarjeta. ng-if arregla eso al no incluir el código en absoluto. (Solo marque aquí si hay algunas sorpresas ocultas usando ng-if en lugar de ng-show)
ngIf realiza una manipulación en el DOM eliminando o recreando el elemento.
Mientras que ngShow aplica reglas css para ocultar / mostrar cosas.
Para la mayoría de los casos (no siempre) , resumiría esto como, si necesita una verificación única para mostrar / ocultar cosas, use ng-if
, si necesita mostrar / ocultar cosas según las acciones del usuario en la pantalla (como marcado una casilla de verificación y luego mostrar el cuadro de texto, desmarcar y luego ocultar el cuadro de texto, etc.), luego usarng-show
Una diferencia interesante en ng-if y ng-show es:
SEGURIDAD
Los elementos DOM presentes en el bloque ng-if no se representarán en caso de que su valor sea falso
donde, como en el caso de ng-show, el usuario puede abrir su ventana Inspeccionar elemento y establecer su valor en VERDADERO.
Y con un grito, se muestra todo el contenido que estaba destinado a estar oculto, lo cual es una violación de seguridad. :)
ng-if
el modelo, agregado porng-model
, ya no existe.