Angularjs: gli elementi ng-cloak / ng-show lampeggiano


231

Ho un problema in angular.js con direttiva / classe ng-cloako ng-show.

Chrome funziona bene, ma Firefox sta causando un battito di ciglia di elementi con ng-cloako ng-show. IMHO è causato dalla conversione ng-cloak/ ng-showin style="display: none;", probabilmente il compilatore javascript di Firefox è un po 'più lento, quindi gli elementi appaiono per un po' e poi si nascondono?

Esempio:

<ul ng-show="foo != null" ng-cloak>..</ul>

1
se imposti display: nessuno stile su questi elementi inizialmente, risolve il problema?
Akonsu,

3
Ci proverò, stavo provando qualcosa di simile con l'aggiunta di classe (che nasconde l'elemento) e poi rimuovendolo manualmente tramite js, ma sembrava ancora più brutto.
MelkorNemesis,

Risposte:


385

Anche se la documentazione non lo menziona, potrebbe non essere sufficiente aggiungere la display: none;regola al tuo CSS. Nei casi in cui si sta caricando angular.js nel corpo o i modelli non vengono compilati abbastanza presto, utilizzare la ng-cloakdirettiva e includere quanto segue nel 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;
}

Come menzionato nel commento, !importantè importante. Ad esempio, se si dispone del seguente markup

<ul class="nav">
  <li><a href="/foo" ng-cloak>{{bar}}</a></li>
</ul>

e ti capita di usare bootstrap.css, il seguente selettore è più specifico per il tuo ng-cloakelemento

.nav > li > a {
  display: block;
}

Quindi, se includi semplicemente una regola display: none;, la regola di Bootstrap avrà la precedenza e displaysarà impostata su block, quindi vedrai lo sfarfallio prima che il modello venga compilato.


3
Si noti inoltre che questo stesso problema può verificarsi se si sta caricando angular.js utilizzando un caricatore asincrono, come request.js, poiché la regola css in .js non sarà stata analizzata in tempo. La soluzione sopra risolve anche questo scenario.
Johann,

84
Non risolve il problema per me. Non lo so - Penso che i browser siano troppo desiderosi di mostrare le cose inizialmente ...
Andriy Drozdyuk

7
Il browser non dovrebbe MAI eseguire il rendering del DOM senza tener conto del CSS, anche al primo passaggio; sarebbe altamente inefficiente; Ricontrolla la tua configurazione: p
AlexG,

1
come si riavvia domstrap che è stato occultato, una volta caricato il codice del modulo doms?
FutuToad,

Se il CSS sopra non funziona per te, è probabile che il tuo :in ng:cloaknon sia salvato correttamente. Per puro CSS assicurati che la barra rovesciata sia presente. Per i CSS compilati, ad esempio Stilo, lo sarà [ng\\:cloak]. Controlla il tuo CSS compilato per assicurarti che sia corretto.
Joe,

47

Come menzionato nella documentazione , è necessario aggiungere una regola al CSS per nasconderla in base ng-cloakall'attributo:

[ng\:cloak], [ng-cloak], .ng-cloak {
    display: none;
}

Usiamo trucchi simili sul sito "Costruito con Angular", di cui puoi visualizzare l'origine su Github: https://github.com/angular/builtwith.angularjs.org

Spero che aiuti!


4
angular.js aggiunge quella regola di stile all'inizio del documento. Non dovresti davvero aver bisogno di aggiungere questo al tuo CSS. Detto questo, sembra funzionare. La mia ipotesi è perché angular.js non aggiunge il blocco di stile alla testa fino a dopo il caricamento angolare.
ntownsend,

13
Ciò che è veramente menzionato nella documentazione è questo: "Per il miglior risultato, lo script angular.js deve essere caricato nella sezione head del file html; in alternativa , la regola css (sopra) deve essere inclusa nel foglio di stile esterno dell'applicazione. "
Andriy Drozdyuk,

4
In altre parole, se stai aggiungendo i riferimenti agli script nella parte inferiore della pagina (come fanno molte persone); quindi aggiungi la regola al tuo CSS.
GFoley83,

1
Stavo aggiungendo angular.js con require.js, quindi questo mi ha aiutato.
olive

1
Aggiunta la direttiva ng-cloak all'elemento html che contiene la direttiva ng-app. Ha funzionato come un fascino. Esempio: <div ng-cloak ng-app = "my-app">
miniscem

33

Assicurati che AngularJS sia incluso nel headcodice HTML. Vedi ngCloak doc :

Per il miglior risultato, lo script angular.js deve essere caricato nella sezione head del file html; in alternativa, la regola CSS (sopra) deve essere inclusa nel foglio di stile esterno dell'applicazione.


3
sì! Non riesco a capire perché le persone di tutto il mondo sembrano raccomandare di caricare angular.js alla fine della pagina. Mi sento meglio se Angular prende il controllo fin dall'inizio. Il mio ng-cloaksta lavorando ora.
Ivan Ferrer Villa,

2
Sono d'accordo - la cosa sugli script caricati alla fine viene dal normale sviluppo web in cui vuoi che la pagina mostri qualcosa prima che js faccia la sua cosa, ma nel caso dell'angolare, vuoi davvero il contrario.
vedi più nitido il

1
E prima di caricare qualsiasi foglio di stile. Includere Angular nel headfoglio di stile ma dopo, non risolve il problema.
AgmLauncher,

27

Non ho mai avuto molta fortuna con ngCloak. Continuo a tremolare nonostante tutto quanto menzionato sopra. L'unico modo infallibile per evitare lo sfarfallio è inserire il contenuto in un modello e includerlo. In una SPA, l'unico HTML che verrà valutato prima di essere compilato da Angular è la tua pagina index.html principale.

Basta prendere tutto all'interno del corpo e incollarlo in un file separato e quindi:

<ng-include src="'views/indexMain.html'"></ng-include>

Non dovresti mai avere sfarfallio in quel modo poiché Angular compilerà il modello prima di aggiungerlo al DOM.


1
Esattamente quello che uso: pulito e semplice, nessun trucco doloroso.
Dmitri Zaitsev,

2
Si noti che ng-includegenera un'ulteriore richiesta AJAX per recuperare il contenuto dal server. Ho imparato a mie spese che non dovresti mai usare ng-includedentro ng-repeat, per esempio.
jsuddsjr,

1
ha funzionato per me. ricordati di tenerti ng-appfuori dal ng-includetuo markup.
GraehamF,

2
Questa soluzione funziona meglio, senza alcun singhiozzo. Se possibile, utilizzare questa soluzione.
idungotnosn,

2
Questa soluzione ha risolto una situazione davvero fastidiosa. Grazie!
Maxwelll,

22

ngBind e ngBindTemplate sono alternative che non richiedono 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>

1
Risposta semplice e piacevole. ng-bindè un buon modo per evitare il "flash parentesi graffa" o dover utilizzare ng-cloaka livello di tag, anche se alcune persone pensano che renda il codice meno leggibile. Per loro, non vedo un motivo per non mescolare i due approcci.
Dave Everitt,

1
ng-bind è un approccio molto migliore al problema in quanto le altre risposte richiedono di caricare la prima angolare, nessuna parentesi graffa lampeggia affatto in nessuna circostanza
legramira,

20

Oltre alla risposta accettata se stai utilizzando un metodo alternativo per attivare ng-cloak ...

Potresti anche voler aggiungere alcune specificità aggiuntive al tuo CSS / MENO:

[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],
.ng-cloak, .x-ng-cloak,
.ng-hide {
    display: none !important;
}

1
Questo ha funzionato per il mio caso d'uso, quando nessuno dei precedenti sembrava fare il lavoro.
Porlune,

15

Ho avuto un problema simile e ho scoperto che se hai una classe che contiene transizioni, l'elemento lampeggerà. Ho provato ad aggiungere ng-cloak senza successo, ma rimuovendo la transizione il pulsante ha smesso di lampeggiare.

Sto usando la struttura ionica e il contorno del pulsante ha questa transizione

.button-outline {
  -webkit-transition: opacity .1s;
  transition: opacity .1s;
}

Basta sovrascrivere la classe per rimuovere la transizione e il pulsante smetterà di lampeggiare.

Aggiornare

Ancora su ionico c'è uno sfarfallio quando si utilizza ng-show / ng-hide. L'aggiunta del seguente CSS lo risolve:

.ng-hide-add,
.ng-hide-remove {
  display: none !important;
}

Fonte: http://forum.ionicframework.com/t/beta-14-ng-hide-show/14270/9


1
Ma ciò non disabiliterebbe le animazioni per le direttive ng-hide / show?
Kushagra Gour,

1
Non ricordo. Hai provato e ha disabilitato le animazioni?
Seb Fanals,

1
Grazie. Questo è un problema molto speciale su ionico. Ho aggiunto .button-clear, .button-icon, .button-outline { @include transition(opacity 0s); }al mio scss.
hgoebl,

9

Ho avuto un problema in cui a <div ng-show="expression">sarebbe stato inizialmente visibile per una frazione di secondo, anche se "espressione" era inizialmente falsa, prima che la direttiva ng-show avesse avuto la possibilità di funzionare.

La soluzione che ho usato è stata quella di aggiungere manualmente la classe "ng-hide", come in <div ng-show="expression" ng-hide>, per assicurarsi che fosse inizialmente nascosta. La direttiva ng-show aggiungerà / rimuoverà la classe ng-hide come necessario dopo ciò.


1
wow, tra tutte le opzioni che ho provato, questo ha funzionato. Grazie!
Nikola,

Soluzione migliore! Questo mi ha fatto impazzire per diversi mesi! Grazie!
abelabbesnabi,

Sto usando il framework ionico e questa è l'unica risposta che funziona davvero
Mikel,

7

Prova a spegnere Firebug . Sono serio. Questo aiuta nel mio caso.

Applica la risposta accettata e assicurati che Firebug in Firefox sia disattivato : premi F12 quindi disattiva Firebug per questa pagina - piccolo pulsante nell'angolo in alto a destra.


Sì, lo ha fatto per me Grazie!
MadeInDreams,

Grazie, mi stava facendo impazzire. Strano bug
Stephen Simpson,

6

In realtà ci sono due problemi separati che possono causare il problema dello sfarfallio e potresti trovarti ad affrontare uno o entrambi.

Problema 1: ng-cloak viene applicato troppo tardi

Questo problema è stato risolto come descritto in molte delle risposte in questa pagina per assicurarsi che AngularJS sia caricato nella testa. Vedi ngCloak doc :

Per il miglior risultato, lo script angular.js deve essere caricato nella sezione head del file html; in alternativa, la regola CSS (sopra) deve essere inclusa nel foglio di stile esterno dell'applicazione.

Problema 2: ng-cloak viene rimosso troppo presto

È molto probabile che questo problema si verifichi quando nella tua pagina sono presenti molti CSS con regole che si sovrappongono l'una all'altra e che i livelli più profondi di CSS lampeggiano prima dell'applicazione del livello superiore.

Le soluzioni jQuery nelle risposte che comportano l'aggiunta style="display:none"al tuo elemento risolvono questo problema purché lo stile venga rimosso abbastanza tardi (in realtà queste soluzioni risolvono entrambi i problemi). Tuttavia, se preferisci non aggiungere stili direttamente al tuo HTML, puoi ottenere gli stessi risultati usando ng-show.

A partire dall'esempio della domanda:

<ul ng-show="foo != null" ng-cloak>..</ul>

Aggiungi una regola ng-show aggiuntiva al tuo elemento:

<ul ng-show="isPageFullyLoaded && (foo != null)" ng-cloak>..</ul>

(È necessario continuare ng-cloakper evitare il problema 1).

Quindi nel tuo set app.run isPageFullyLoaded:

app.run(['$rootScope', function ($rootScope) {
    $rootScope.$safeApply = function (fn) {
        $rootScope.isPageFullyLoaded = true;
    }
}]);

Tieni presente che, in base esattamente a ciò che stai facendo, app.run potrebbe essere o meno il posto migliore da impostare isPageFullyLoaded. L'importante è assicurarsi che isPageFullyLoadedvenga impostato su true dopo che qualunque cosa tu non voglia sfarfallio è pronta per essere rivelata all'utente.

Sembra che il Problema 1 sia il problema che l'OP sta colpendo, ma altri stanno scoprendo che la soluzione non funziona o funziona solo in parte perché stanno colpendo il Problema 2 invece o anche.

Nota importante: assicurati di applicare entrambe le soluzioni a entrambi i mantelli ng applicati troppo tardi e rimossi a breve. Risolvere solo uno di questi problemi potrebbe non alleviare i sintomi.


1
questo mi ha risolto "lo script deve essere caricato nella sezione head"
aliopi il

4

Abbiamo riscontrato questo problema nella nostra azienda e risolto aggiungendo "display: none" allo stile CSS per quegli elementi sfarfallanti di ng-show. Non abbiamo dovuto usare affatto ng-cloak. A differenza di altri in questo thread, abbiamo riscontrato questo problema in Safari ma non in Firefox o Chrome, probabilmente a causa del bug pigro di ridipintura di Safari in iOS7 .


3

Per quello che vale, ho avuto un problema simile che ng-mantello non funzionava. Potrebbe valere la pena controllare l'app / il sito con la cache abilitata per riutilizzare i file di origine per vedere se ciò aiuta.

Con il mio rodaggio con sfarfallio, stavo testando con DevTools aperto e cache disabilitata. Lasciare il pannello chiuso con la cache abilitata ha risolto il mio problema.


3

Mantenere le seguenti istruzioni nel tag head risolto questo problema

<style type="text/css">
    [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
    display: none !important;
}
</style>

documentazione ufficiale


3

Non sono riuscito a far funzionare nessuno di questi metodi, quindi alla fine ho fatto quanto segue. Per l'elemento che vuoi inizialmente nascosto:

<div <!--...--> style="display: none;" ng-style="style">

Quindi nel controller, aggiungilo nella parte superiore o superiore:

$scope.style = { display: 'block' };

In questo modo, l'elemento viene inizialmente nascosto e mostra solo quando il codice del controller è stato effettivamente eseguito.

Puoi adattare il posizionamento alle tue esigenze, magari aggiungendo un po 'di logica. Nel mio caso, passo a un percorso di accesso se non attualmente connesso e non volevo che la mia interfaccia tremolasse in anticipo, quindi ho impostato $scope.styledopo il controllo di accesso.


2

È meglio usare ng-ifinvece di ng-show. ng-if rimuove completamente e ricrea l'elemento nel DOM e aiuta a evitare il lampeggiamento di ng-shows.


ma distrugge anche eventuali plugin in esecuzione su quella parte della dom ... (ad esempio: jquery ui)
Geert Bellemans,


2

faresti meglio a fare riferimento al documento angolare, perché la versione [1.4.9] ha un aggiornamento al di sotto che lo rende in grado di supportare la direttiva data-ng-cloak.

[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
  display: none !important;
}

2

Ho provato la soluzione ng-cloak sopra ma ha ancora problemi intermittenti con Firefox. L'unica soluzione che ha funzionato per me è ritardare il caricamento del modulo fino a quando Angular non è completamente caricato.

Ho semplicemente aggiunto ng-init nell'app e utilizzo ng-if sul lato modulo per verificare se la variabile che ho impostato è già caricata.

<div ng-app="myApp" ng-init="loaded='yes'"> 
   <form ng-if="loaded.length > 0">
      <!--all my elements here-->
   </form>
</div>

1

Oltre ad altre risposte, se trovi che il flash del codice modello è ancora presente, è probabile che tu abbia i tuoi script in fondo alla pagina e ciò significa che la direttiva ng-cloak direttamente non funzionerà. Puoi spostare i tuoi script in testa o creare una regola CSS.

I documenti dicono "Per il miglior risultato, lo script angular.js deve essere caricato nella sezione head del documento html; in alternativa, la regola css sopra deve essere inclusa nel foglio di stile esterno dell'applicazione."

Ora, non deve essere un foglio di stile esterno ma solo un elemento nella testa.

<style type="text/css">
  .ng-cloak {
    display: none !important;
  }
</style>

fonte: https://docs.angularjs.org/api/ng/directive/ngCloak


1

Ho provato tutte le soluzioni pubblicate qui e ho ancora sfarfallio in Firefox.

Se aiuta qualcuno, l'ho risolto aggiungendo style="display: none;"al div contenuto principale, quindi usando jQuery (lo stavo già usando nella pagina) $('#main-div-id').show();una volta che tutto è stato caricato dopo aver ottenuto i dati dal server;


Ho scoperto che questa era l'unica soluzione che ha funzionato per me, ma volevo evitare di usare JQuery, quindi ho trovato un'alternativa. Vedi la mia risposta qui: stackoverflow.com/a/42527700/4214694
Andrew Downes

1

In realtà ho trovato il suggerimento dal Web Log di Rick Strahl risolto perfettamente il mio problema (dato che a volte avevo ancora lo strano problema con ng-cloak che lampeggiava {{code}}, specialmente durante l'esecuzione di Firebug):

L'opzione nucleare: nascondere il contenuto manualmente

L'uso del CSS esplicito è la scelta migliore, quindi non dovrebbe mai essere necessario quanto segue. Ma lo citerò qui in quanto fornisce alcune informazioni su come nascondere / mostrare manualmente i contenuti caricati per altri framework o nei propri modelli basati sul markup.

Prima di capire che potevo incorporare esplicitamente lo stile CSS nella pagina, avevo cercato di capire perché ng-cloak non stava facendo il suo lavoro. Dopo aver perso un'ora ad arrivare da nessuna parte, ho finalmente deciso di nascondere e mostrare manualmente il contenitore. L'idea è semplice: inizialmente nascondi il contenitore, quindi mostralo una volta che Angular ha completato l'elaborazione e la rimozione del markup del modello dalla pagina.

È possibile nascondere manualmente il contenuto e renderlo visibile dopo che Angular ha ottenuto il controllo. Per fare questo ho usato:

<div id="mainContainer" class="mainContainer boxshadow"
    ng-app="app" style="display:none">

Notare la visualizzazione: nessuno stile che nasconde esplicitamente l'elemento inizialmente nella pagina.

Quindi una volta che Angular ha eseguito la sua inizializzazione ed elaborato in modo efficace il markup del modello sulla pagina, è possibile mostrare il contenuto. Per Angular questo evento 'pronto' è la funzione app.run ():

app.run( function ($rootScope, $location, cellService) {        
    $("#mainContainer").show();
    
});

Questo rimuove efficacemente il display: nessuno stile e il contenuto viene visualizzato. Quando app.run () viene attivato, il DOM è pronto per essere visualizzato con i dati riempiti o almeno i dati vuoti: Angular ha ottenuto il controllo.


Ho scoperto che questa era l'unica soluzione che funzionava per me, ma volevo evitare di usare JQuery e ho trovato un'alternativa. Vedi la mia risposta qui: stackoverflow.com/a/42527700/4214694
Andrew Downes

1

Ho provato tutte le risposte sopra e niente ha funzionato. Usando ionic per sviluppare un'app ibrida e stavo cercando di fare in modo che un messaggio di errore non sfarfallasse. Ho finito per risolvere il mio problema aggiungendo una classe ng-hide al mio elemento. Il mio div ha già ng-show per mostrare l'elemento in caso di errore. Aggiungendo ng-hide impostare il div in modo che non venga visualizzato prima del caricamento dell'angolare. Non è necessario nessun mantello o aggiungere angolare alla testa.


1

AS dalla discussione sopra

[ng-cloak] {
                display: none;
            }

è il modo perfetto per risolvere il problema.


1

Sto usando ng-show in una direttiva per mostrare e nascondere i popup.

<div class="..." ng-show="showPopup">

Nessuna delle precedenti ha funzionato per me, e usare ng-if invece di ng-show sarebbe stato eccessivo. Ciò implicherebbe la rimozione e l'aggiunta dell'intero contenuto popup nel DOM ad ogni singolo clic. Invece ho aggiunto un ng-if nello stesso elemento per assicurarmi che non venga visualizzato al caricamento del documento:

<div class="..." ng-show="showPopup" ng-if="popupReady">

Successivamente ho aggiunto l'inizializzazione al controller responsabile di questa direttiva con un timeout:

$timeout(function () {
    $scope.popupReady = true;
});

In questo modo ho eliminato il problema dello sfarfallio ed evitato l'operazione costosa di inserimento DOM ad ogni singolo clic. Questo ha comportato una spesa per l'utilizzo di due variabili dell'ambito per lo stesso scopo anziché uno, ma finora è sicuramente l'opzione migliore.


1

Lampi provati ng-cloakma ancora brevi. Di seguito il codice li libera completamente.

<body style="display:none;" ng-style="{'display':'block'}">

1

Nessuna delle soluzioni sopra elencate ha funzionato per me. Ho quindi deciso di esaminare la funzione effettiva e mi sono reso conto che quando "$ scope.watch" è stato attivato, stava inserendo un valore nel campo del nome che non era previsto. Quindi nel codice ho impostato e oldValue e newValue quindi

$scope.$watch('model.value', function(newValue, oldValue) {
if (newValue !== oldValue) {
validateValue(newValue);
}
});

Essenzialmente quando scope.watch viene attivato in questo caso, AngularJS monitora le modifiche alla variabile name (model.value)


0

Avrei avvolto il <ul>con a<div ng-cloak>


2
Non dovrebbe aver bisogno di avvolgere il <ul>. ng-cloakcoprirà qualunque elemento venga applicato, così come i discendenti di quell'elemento.
btford,

0

Personalmente ho deciso di utilizzare l' ng-classattributo anziché ilng-show . Ho avuto molto più successo seguendo questa strada soprattutto per le finestre pop-up che non sono sempre mostrate di default.

Quello che era <div class="options-modal" ng-show="showOptions"></div>

è ora: <div class="options-modal" ng-class="{'show': isPrintModalShown}">

con CSS per display: noneimpostazione predefinita la classe modale opzioni . La classe show contiene il display:blockCSS.


-2

Evita l'interruzione di linea

<meta http-equiv="Content-Security-Policy"              content="
default-src 'FOO';   
script-src 'FOO';    
style-src  'FOO'; 
font-src 'FOO';">

Funziona con Firefox 45.0.1

<meta http-equiv="Content-Security-Policy"              content="    default-src 'FOO';    script-src 'FOO';     style-src  'FOO';    font-src 'FOO';">
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.