2014-11-14 7 views
66

Sto tentando di mostrare o nascondere un indicatore di caricamento su un pulsante quando una richiesta è occupata. Lo faccio con angolare cambiando la variabile $ scope.loading quando una richiesta si sta caricando o quando ha finito il caricamento.angolare ng-if o ng-show risponde lentamente (2 secondi di ritardo?)

$scope.login = function(){ 
    $scope.loading = true; 
    apiFactory.getToken() 
     .success(function(data){ 

     }) 
     .error(function(error){ 

     }) 
     .finally(function(){ 
       $timeout(function() { 
       $scope.loading = false; 
       }, 0); 
     }); 
}; 

Nel frontend:

<button ng-disabled="loading" class="button button-outline button-positive" type="submit"> 
Log in 
<span ng-if="loading" class="ion-refreshing"></span> 
</button> 

Questo funziona bene, ma l'icona di carico (ione-rinfrescante) viene mostrato per circa 2 secondi, mentre la variabile $ campo di applicazione è aggiornato immediatamente. Ho provato $ scope. $ Apply ma non sembra essere quello che non va qui, lo scope viene aggiornato bene e subito dopo la richiesta. È solo l'icona che non risponde abbastanza velocemente.

Grazie per avermi aiutato a capire questo!

+2

Eventuali animazioni coinvolti? – tasseKATT

+0

Negativo. Nessuna animazione coinvolta. L'uso di ng-class sembra invece aiutare. – Jorre

+0

Sto avendo lo stesso o un problema simile.L'ambito viene aggiornato immediatamente e correttamente: l'ho verificato registrando i messaggi dalle funzioni '$ scope' che' ng-if' usa per scoprire se gli elementi rilevanti devono essere mostrati. Tuttavia, i pulsanti con 'ng-if' rimangono erroneamente visibili, o nascosti, per qualche secondo. Quindi, dopo un breve intervallo di tempo, tutti i pulsanti assumono gli stati visibili/nascosti previsti. - Ho lavorato su questo usando invece 'ng-hide'. Versione angolare 1.2.16. – KajMagnus

risposta

33

Ho avuto lo stesso problema e ho risolto il problema utilizzando ng-class con il nome di classe "nascosto" per nascondere l'elemento anziché utilizzare ng-if o ng-show/ng-hide.

+2

Sembra funzionare molto più velocemente di ng-if o ng-show ... – Vall3y

+1

Sembra correlato con animazioni e/o gestori di eventi. Non sono proprio sicuro del motivo per cui gli altri sono lenti, ma mi piacerebbe sapere come –

+0

come si può fare? – jsmedmar

107

Provare a rimuovere ngAnimate se non lo si utilizza dalla tua applicazione di configurazione e la pagina index.html:

angular.module('myApp', [...'ngAnimate',...]) 

@Spock; se ancora richiedere l'uso di ngAnimate poi lasciare la vostra applicazione di configurazione intatta e basta aggiungere il seguente CSS:

.ng-hide.ng-hide-animate{ 
    display: none !important; 
} 

Che vi nascondere l'icona animata subito dopo la sua condizione è soddisfatta.

Come puoi vedere stiamo impostando .ng-hide-animate su hidden. Questo è ciò che causa il ritardo mentre attende il completamento dell'animazione. Puoi aggiungere un'animazione al tuo evento hide come implica il nome della classe invece di nasconderla come nell'esempio sopra.

+1

Avevo una pagina semplice con solo un paio di 'ng-if',' ng-show' che era visibilmente lento. Ho rimosso 'ngAnimate' e ha risolto il problema per me. Grazie! –

+1

Questo risolve un problema che stavo facendo anche io ... Sai perché la presenza di ngAnimate stava causando la transizione lenta? – Clark

+0

Aveva lo stesso problema - rimuovere ngAnimate lo ha risolto .. ma questo non va bene .. molti moduli hanno bisogno di ngAnimate per fare animazioni fantastiche .. cosa fare? ngAnimattias dove sei? :) – Spock

10

ho trovato alcune soluzioni here, ma la cosa migliore per me era l'override del styling per la classe .NG-animate:

.ng-animate.no-animate { 
    transition: 0s none; 
    -webkit-transition: 0s none; 
    animation: 0s none; 
    -webkit-animation: 0s none; 
} 

in HTML:

<button ng-disabled="loading" class="button button-outline button-positive" type="submit"> 
    Log in 
    <span ng-if="loading" class="ion-refreshing no-animate"></span> 
</button> 

Questo è un esempio: http://jsfiddle.net/9krLr/27/

Spero di aiutarti.

3

Ero di fronte a un problema simile, ho usato $scope.$evalAsync() per forzare l'aggiornamento del binding.

Funziona come un fascino.

Evitare l'uso di $scope.$apply in quanto può entrare in conflitto con una fase $ digest già in esecuzione.

if(selectedStatistics.length === 0 || selectedWorkgroups.length === 0){ 
    ctrl.isSaveDisabled = true; 
    $scope.$evalAsync(); 
} else{ 
    ctrl.isSaveDisabled = false; 
    $scope.$evalAsync(); 
} 
0

nella versione angolare 1.5.x aggiungendo $scope.$apply() dopo il cambiamento nella condizione di fatto il lavoro per me qui è una funzione di esempio

$scope.addSample = function(PDF) 
     { 
      var validTypes ="application/pdf"; 
      if(PDF.type == validTypes) 
      { 
       //checking if the type is Pdf and only pdf 
       $scope.samplePDF= PDF.files[0]; 
       $scope.validError = false; 
       $scope.$apply(); 
      } 

      else 
      { 
       $scope.validError = true; 
       $scope.samplePDF= null; 
       $scope.$apply(); 
      } 


     }