javascript - examples - ng-show angularjs
Angularjs: los elementos ng-cloak/ng-show parpadean (29)
Tengo un problema en angular.js con directiva / clase ng-cloak
o ng-show
.
Chrome funciona bien, pero Firefox está causando un parpadeo de elementos con ng-cloak
o ng-show
. En mi humilde opinión es causado por la conversión ng-cloak
/ ng-show
a style="display: none;"
, probablemente el compilador de JavaScript de Firefox sea un poco más lento, por lo que los elementos aparecen por un tiempo y luego se esconden?
Ejemplo:
<ul ng-show="foo != null" ng-cloak>..</ul>
AS de la discusión anterior
[ng-cloak] {
display: none;
}
Es la manera perfecta de resolver el problema.
Además de la respuesta aceptada si está utilizando un método alternativo para activar ng-cloak ...
También es posible que desee agregar algunas especificidades adicionales a su CSS / MENOS:
[ng/:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],
.ng-cloak, .x-ng-cloak,
.ng-hide {
display: none !important;
}
Además de otras respuestas, si aún está apareciendo el flash del código de plantilla, es probable que tenga sus scripts en la parte inferior de la página y eso significa que la directiva ng-cloak no funcionará. Puede mover sus scripts a la cabeza o crear una regla de CSS.
Los documentos dicen "Para obtener el mejor resultado, la secuencia de comandos angular.js se debe cargar en la sección principal del documento html; alternativamente, la regla css anterior debe incluirse en la hoja de estilo externa de la aplicación".
Ahora, no tiene que ser una hoja de estilo externa sino solo un elemento en la cabeza.
<style type="text/css">
.ng-cloak {
display: none !important;
}
</style>
Asegúrese de que AngularJS esté incluido en el head
del HTML. Ver ngCloak doc :
Para obtener el mejor resultado, el script angular.js debe cargarse en la sección principal del archivo html; alternativamente, la regla css (arriba) debe incluirse en la hoja de estilo externa de la aplicación.
Aunque la documentación no lo menciona, puede que no sea suficiente para agregar la display: none;
gobernar a tu CSS. En los casos en los que cargue angular.js en el cuerpo o las plantillas no se compilan lo suficientemente pronto, use la directiva ng-cloak
e incluya lo siguiente en su CSS:
/*
Allow angular.js to be loaded in body, hiding cloaked elements until
templates compile. The !important is important given that there may be
other selectors that are more specific or come later and might alter display.
*/
[ng/:cloak], [ng-cloak], .ng-cloak {
display: none !important;
}
Como se menciona en el comentario, lo !important
es importante. Por ejemplo, si tiene el siguiente marcado
<ul class="nav">
<li><a href="/foo" ng-cloak>{{bar}}</a></li>
</ul>
y resulta que estás usando bootstrap.css
, el siguiente selector es más específico para tu elemento ng-cloak
''ed
.nav > li > a {
display: block;
}
Así que si incluyes una regla con simplemente display: none;
La regla de Bootstrap tendrá prioridad y la display
se configurará para block
, por lo que verá el parpadeo antes de que se compile la plantilla.
Como se menciona en la documentación , debe agregar una regla a su CSS para ocultarla según el atributo ng-cloak
:
[ng/:cloak], [ng-cloak], .ng-cloak {
display: none;
}
Usamos trucos similares en el sitio "Construido con Angular", que puede ver la fuente en Github: https://github.com/angular/builtwith.angularjs.org
¡Espero que ayude!
De hecho, encontré que la sugerencia del Registro Web de Rick Strahl solucionó mi problema a la perfección (ya que todavía tenía un problema extraño con ng-cloak parpadeando en bruto {{código}} a veces, especialmente al ejecutar Firebug):
La opción nuclear: ocultar el contenido manualmente.
Usar la CSS explícita es la mejor opción, por lo que nunca debería ser necesario lo siguiente. Pero lo mencionaré aquí, ya que brinda una idea de cómo puede ocultar / mostrar el contenido manualmente durante la carga de otros marcos o en sus propias plantillas basadas en marcado.
Antes de darme cuenta de que podía integrar explícitamente el estilo CSS en la página, había tratado de averiguar por qué ng-cloak no estaba haciendo su trabajo. Después de perder una hora en llegar a ninguna parte, finalmente decidí ocultarme manualmente y mostrar el contenedor. La idea es simple: inicialmente oculte el contenedor, luego muéstrelo una vez que Angular haya realizado su procesamiento inicial y se haya eliminado el marcado de la plantilla de la página.
Puede ocultar manualmente el contenido y hacerlo visible después de que Angular haya tomado el control. Para ello utilicé:
<div id="mainContainer" class="mainContainer boxshadow"
ng-app="app" style="display:none">
Observe la pantalla: ningún estilo que oculte explícitamente el elemento inicialmente en la página.
Luego, una vez que Angular haya ejecutado su inicialización y haya procesado efectivamente el marcado de la plantilla en la página, puede mostrar el contenido. Para Angular, este evento ''listo'' es la función app.run ():
app.run( function ($rootScope, $location, cellService) {
$("#mainContainer").show();
…
});
Esto elimina efectivamente la pantalla: ninguno estilo y el contenido se muestra. Cuando app.run () se activa, el DOM está listo para mostrarse con datos completos o al menos con datos vacíos: Angular ha tomado el control.
En realidad, hay dos problemas separados que pueden causar el problema de parpadeo y podría enfrentar uno o ambos.
Problema 1: la capa de ng se aplica demasiado tarde
Este problema se resuelve como se describe en muchas de las respuestas en esta página para asegurarse de que AngularJS esté cargado en la cabeza. Ver ngCloak doc :
Para obtener el mejor resultado, el script angular.js debe cargarse en la sección principal del archivo html; alternativamente, la regla css (arriba) debe incluirse en la hoja de estilo externa de la aplicación.
Problema 2: se quita la capa ng demasiado pronto
Este problema es más probable que ocurra cuando tiene una gran cantidad de CSS en su página con reglas en cascada una sobre otra y las capas más profundas de CSS se activan antes de que se aplique la capa superior.
Las soluciones de jQuery en respuestas que incluyen agregar style="display:none"
a su elemento resuelven este problema siempre que el estilo se elimine lo suficientemente tarde (de hecho, estas soluciones resuelven ambos problemas). Sin embargo, si prefiere no agregar estilos directamente a su HTML, puede lograr los mismos resultados usando ng-show
.
Comenzando con el ejemplo de la pregunta:
<ul ng-show="foo != null" ng-cloak>..</ul>
Agrega una regla adicional ng-show a tu elemento:
<ul ng-show="isPageFullyLoaded && (foo != null)" ng-cloak>..</ul>
(Es necesario mantener ng-cloak
para evitar el problema 1).
Luego, en tu conjunto de isPageFullyLoaded
ejecute isPageFullyLoaded
:
app.run([''$rootScope'', function ($rootScope) {
$rootScope.$safeApply = function (fn) {
$rootScope.isPageFullyLoaded = true;
}
}]);
Tenga en cuenta que dependiendo de lo que esté haciendo exactamente, app.run puede o no ser el mejor lugar para configurar isPageFullyLoaded
. Lo importante es asegurarse de que isPageFullyLoaded
se establezca en true después de lo que sea que no quieras que parpadee y esté listo para ser revelado al usuario.
Parece que el Problema 1 es el problema con el que está golpeando el OP, pero otros encuentran que la solución no funciona o solo funciona parcialmente porque están golpeando el Problema 2 en su lugar o también.
Nota importante: asegúrese de aplicar soluciones tanto para el manto ng que se aplica demasiado tarde Y que se retirará pronto. Resolver solo uno de estos problemas puede no aliviar los síntomas.
Es mejor usar ng-if
lugar de ng-show
. ng-if
elimina y recrea completamente el elemento en el DOM y ayuda a evitar que ng-shows parpadee.
Estoy usando ng-show en una directiva para mostrar y ocultar ventanas emergentes.
<div class="..." ng-show="showPopup">
Nada de lo anterior funcionó para mí, y usar ng-if en lugar de ng-show sería una exageración. Eso implicaría eliminar y agregar todo el contenido emergente en el DOM con cada clic. En su lugar, agregué un ng-if en el mismo elemento para asegurarme de que no se muestre en la carga del documento:
<div class="..." ng-show="showPopup" ng-if="popupReady">
Luego agregué la inicialización en el controlador responsable de esta directiva con un tiempo de espera:
$timeout(function () {
$scope.popupReady = true;
});
De esta manera, eliminé el problema de parpadeo y evité la costosa operación de la inserción de DOM con cada clic. Esto tuvo el costo de usar dos variables de alcance para el mismo propósito en lugar de una, pero hasta ahora esta es definitivamente la mejor opción.
Estoy usando un marco iónico, agregar el estilo css podría no funcionar en ciertas circunstancias, puedes intentar usar ng-if en lugar de ng-show / ng-hide
Evita el salto de línea
<meta http-equiv="Content-Security-Policy" content="
default-src ''FOO'';
script-src ''FOO'';
style-src ''FOO'';
font-src ''FOO'';">
Funciona con Firefox 45.0.1
<meta http-equiv="Content-Security-Policy" content=" default-src ''FOO''; script-src ''FOO''; style-src ''FOO''; font-src ''FOO'';">
Intenté ng-cloak
pero todavía breve parpadeos. Debajo de código deshacerse de ellos completamente.
<body style="display:none;" ng-style="{''display'':''block''}">
Intenta apagar el Firebug . Lo digo en serio. Esto ayuda en mi caso.
Aplique la respuesta aceptada y luego asegúrese de que Firebug en su Firefox esté apagado : presione F12 y luego apague Firebug para esta página - botón pequeño en la esquina superior derecha.
Mantener las siguientes afirmaciones en la etiqueta de cabecera solucionó este problema
<style type="text/css">
[ng/:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
display: none !important;
}
</style>
Me gustaría envolver el <ul>
con un <div ng-cloak>
Ninguna de las soluciones enumeradas anteriormente funcionó para mí. Entonces decidí ver la función real y me di cuenta de que cuando se activaba "$ scope.watch", estaba poniendo un valor en el campo de nombre que no estaba destinado a ser el caso. Así que en el código que establezco y oldValue y newValue entonces
$scope.$watch(''model.value'', function(newValue, oldValue) {
if (newValue !== oldValue) {
validateValue(newValue);
}
});
Esencialmente, cuando se activa scope.watch en este caso, AngularJS monitorea los cambios en la variable de nombre (valor de modelo)
No pude hacer funcionar ninguno de estos métodos, así que eventualmente hice lo siguiente. Para el elemento que deseas inicialmente oculto:
<div <!--...--> style="display: none;" ng-style="style">
Luego, en tu controlador, agrega esto en o cerca de la parte superior:
$scope.style = { display: ''block'' };
De esta manera, el elemento está inicialmente oculto y solo se muestra cuando el código del controlador se ha ejecutado realmente.
Puede ajustar la ubicación a sus necesidades, quizás agregando algo de lógica. En mi caso, cambio a una ruta de inicio de sesión si no estoy conectado actualmente, y no quiero que mi interfaz parpadee de antemano, así que configuro $scope.style
después de la verificación de $scope.style
sesión.
Nos topamos con este problema en nuestra empresa y lo resolvimos agregando "display: none" al estilo CSS para esos elementos parpadeantes de ng-show. No tuvimos que usar ng-manto en absoluto. A diferencia de otros en este hilo, experimentamos este problema en Safari pero no en Firefox o Chrome, posiblemente debido a un error de repintado perezoso de Safari en iOS7 .
Nunca he tenido mucha suerte usando ngCloak. Todavía tengo parpadeo a pesar de todo lo mencionado anteriormente. La única manera segura de evitar el flicking es colocar su contenido en una plantilla e incluirla. En un SPA, el único HTML que se evaluará antes de ser compilado por Angular es su página index.html principal.
Solo toma todo dentro del cuerpo y pégalo en un archivo separado y luego:
<ng-include src="''views/indexMain.html''"></ng-include>
Nunca debe tener parpadeo de esa manera, ya que Angular compilará la plantilla antes de agregarla al DOM.
Personalmente, decidí usar el atributo ng-class
lugar de ng-show
. He tenido mucho más éxito en esta ruta, especialmente para ventanas emergentes que no se muestran de forma predeterminada.
Lo que solía ser <div class="options-modal" ng-show="showOptions"></div>
ahora es: <div class="options-modal" ng-class="{''show'': isPrintModalShown}">
con el CSS para la clase de opciones-modal que se display: none
por defecto. La clase show contiene la display:block
CSS.
Por lo que vale, tuve un problema similar ng-manto no funciona. Puede valer la pena revisar su aplicación / sitio con el caché habilitado para reutilizar los archivos de origen para ver si eso ayuda.
Con mi ejecución con parpadeo, estaba probando con DevTools abierto y caché deshabilitado. Dejar el panel cerrado con el almacenamiento en caché habilitado solucionó mi problema.
Probé la solución ng-cloak anterior pero todavía tiene problemas intermitentes con Firefox. La única solución que me funcionó es retrasar la carga del formulario hasta que Angular esté completamente cargado.
Simplemente agregué ng-init en la aplicación y uso ng-if en el lado del formulario para verificar si la variable que configuré ya está cargada.
<div ng-app="myApp" ng-init="loaded=''yes''">
<form ng-if="loaded.length > 0">
<!--all my elements here-->
</form>
</div>
Probé todas las respuestas anteriores y nada funcionó. Usando ionic para desarrollar una aplicación híbrida y estaba tratando de hacer que un mensaje de error no parpadee. Terminé resolviendo mi problema agregando una clase ng-hide a mi elemento. Mi div ya tiene ng-show para mostrar el elemento cuando hay un error. Agregando ng-hide configura el div para que no se muestre antes de cargar el angular. No es necesario ng-manto o agregado angular a la cabeza.
Probé todas las soluciones publicadas aquí y todavía tengo parpadeo en Firefox.
Si ayuda a alguien, lo resolví agregando style="display: none;"
al contenido principal div, luego usar jQuery (ya lo estaba usando en la página) $(''#main-div-id'').show();
una vez que todo fue cargado después de obtener datos del servidor;
Será mejor que haga referencia al documento angular, ya que la versión [1.4.9] se ha actualizado a continuación para que pueda admitir la directiva data-ng-cloak.
[ng/:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
display: none !important;
}
Tuve un problema en el que una <div ng-show="expression">
sería inicialmente visible por una fracción de segundo, aunque la "expresión" era inicialmente falsa, antes de que la directiva ng-show tuviera la oportunidad de ejecutarse.
La solución que utilicé fue agregar manualmente la clase "ng-hide", como en <div ng-show="expression" ng-hide>
, para asegurarse de que comenzara inicialmente oculta. La directiva ng-show agregará / eliminará la clase ng-hide según sea necesario después de eso.
Tuve un problema similar y descubrí que si tienes una clase que contiene transiciones, el elemento parpadeará. Intenté agregar ng-cloak sin éxito, pero al eliminar la transición, el botón dejó de parpadear.
Estoy usando un marco iónico y el contorno del botón tiene esta transición
.button-outline {
-webkit-transition: opacity .1s;
transition: opacity .1s;
}
Simplemente sobrescriba la clase para eliminar la transición y el botón dejará de parpadear.
Actualizar
De nuevo en ionic, hay un parpadeo cuando se usa ng-show / ng-hide. Añadiendo el siguiente CSS lo resuelve:
.ng-hide-add,
.ng-hide-remove {
display: none !important;
}
Fuente: http://forum.ionicframework.com/t/beta-14-ng-hide-show/14270/9
ngBind y ngBindTemplate son alternativas que no requieren CSS:
<div ng-show="foo != null" ng-cloak>{{name}}</div> <!-- requires CSS -->
<div ng-show="foo != null" ng-bind="name"></div>
<div ng-show="foo != null" ng-bind-template="name = {{name}}"></div>