web-dev-qa-db-fra.com

angular ng-if ou ng-show répond lentement

J'essaie d'afficher ou de masquer un indicateur de chargement sur un bouton lorsqu'une demande est occupée. Je le fais avec angular en changeant la variable $ scope.loading quand une requête est en cours de chargement ou quand il est terminé.

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

        })
        .error(function(error){

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

Dans le frontend:

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

Cela fonctionne bien, mais l'icône de chargement (rafraîchissement des ions) s'affiche pendant environ 2 secondes, tandis que la variable $ scope est mise à jour immédiatement. J'ai essayé $ scope. $ Apply mais cela ne semble pas être ce qui ne va pas ici, le scope est mis à jour très bien et immédiatement après la requête. C'est juste l'icône qui ne répond pas assez rapidement.

Merci de m'aider à comprendre cela!

76
Jorre

Essayez de supprimer ngAnimate si vous ne l'utilisez pas à partir de la page de configuration de votre application et de la page index.html:

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

@Spock; Si vous avez toujours besoin d'utiliser ngAnimate, laissez la configuration de votre application intacte et ajoutez simplement le code CSS suivant:

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

Cela masquera l'icône animée dès que votre condition aura été remplie.

Comme vous pouvez le constater, nous définissons .ng-hide-animate sur hidden. C’est ce qui cause le retard dans l’attente de la fin de l’animation. Vous pouvez ajouter une animation à votre événement de masquage comme l'indique le nom de la classe au lieu de la masquer comme dans l'exemple ci-dessus.

118
Palvinder

J'avais le même problème et je l'ai corrigé en utilisant ng-class avec le nom de classe 'hidden' pour masquer l'élément au lieu d'utiliser ng-if ou ng-show/ng-hide. 

37
neimad

J'ai trouvé quelques solutions ici , mais le mieux pour moi était de remplacer le style de la classe .ng-animate:

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

En 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>

Ceci est un exemple: http://jsfiddle.net/9krLr/27/

J'espère vous aider.

12
Ruben Perez

Je faisais face à un problème similaire, j'ai utilisé $scope.$evalAsync() pour forcer la mise à jour de la liaison.

Il fonctionne comme un charme.

Évitez d’utiliser $scope.$apply car il peut entrer en conflit avec une phase $ digest déjà en cours.

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

J'ai eu le même problème lors de l'utilisation

<div *ngIf='shouldShow'>
    <!-- Rest of DIV content here -->
</div>

Dans mon cas, j'ai résolu le problème en ajoutant une classe:

.hidden {
  display: none;
}

puis en ajoutant la classe conditionnellement au lieu d'utiliser *ngIf:

<div [ngClass]="{'hidden': !shouldShow}">
    <!-- Rest of DIV content here -->
</div>

Si je l’utilise toujours de cette façon, j’envisagerais de renommer shouldShow en shouldHide (et d’annuler la logique qui l’assigne), afin de pouvoir l’utiliser comme shouldHide au lieu de !shouldShow. .

Si vous avez display: flex dans votre CSS pour la classe existante de la division, cette propriété d'affichage peut avoir priorité sur la display: hidden. Une solution facile peut être d'utiliser display: none !important à la place, mais il existe souvent de meilleures solutions pour assurer la priorité d'une autre manière. Voici une bonne lecture sur les alternatives .

0

dans la version angulaire 1.5.x ajoutant $scope.$apply() après le changement de condition effectué pour moi voici un exemple de fonction 

$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();
            }


        }
0
mohamed