Winkel ng-if oder ng-show reagiert langsam (2 Sekunden Verzögerung?)

87

Ich versuche, eine Ladeanzeige auf einer Schaltfläche anzuzeigen oder auszublenden, wenn eine Anforderung beschäftigt ist. Ich mache das mit Angular, indem ich die Variable $ scope.loading ändere, wenn eine Anfrage geladen wird oder wenn sie geladen ist.

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

        })
        .error(function(error){

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

Im Frontend:

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

Dies funktioniert einwandfrei, aber das Ladesymbol (Ionenauffrischung) wird ca. 2 Sekunden lang angezeigt, während die Variable $ scope sofort aktualisiert wird. Ich habe $ scope. $ Apply ausprobiert, aber das scheint hier nicht falsch zu sein. Der Bereich wird einwandfrei und unmittelbar nach der Anforderung aktualisiert. Es ist nur das Symbol, das nicht schnell genug reagiert.

Danke, dass du mir geholfen hast, das zu verstehen!

Jorre
quelle
2
Irgendwelche Animationen?
TasseKATT
Negativ. Keine Animationen beteiligt. Die Verwendung von ng-class scheint stattdessen zu helfen.
Jorre
Ich habe das gleiche oder ein ähnliches Problem. Der Bereich wird sofort und korrekt aktualisiert. Ich habe dies überprüft, indem ich Nachrichten mit den $scopeFunktionen protokolliert habe , ng-ifmit denen herausgefunden wird, ob die relevanten Elemente angezeigt werden sollen. Schaltflächen ng-ifbleiben jedoch für einige Sekunden falsch sichtbar oder ausgeblendet. Nach kurzer Zeit nehmen alle Tasten ihren beabsichtigten sichtbaren / verborgenen Zustand an. - Ich habe das umgangen, indem ich ng-hidestattdessen verwendet habe. Winkelversion 1.2.16.
KajMagnus
Gibt es eine Lösung für diejenigen, die keine Animationen verwenden?
Zia Ul Rehman Mughal

Antworten:

124

Versuchen Sie, ngAnimate zu entfernen, wenn Sie es nicht von Ihrer App-Konfigurations- und index.html-Seite verwenden:

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

@Spock; Wenn Sie weiterhin ngAnimate benötigen, lassen Sie Ihre App-Konfiguration unberührt und fügen Sie einfach das folgende CSS hinzu:

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

Dadurch wird das animierte Symbol direkt ausgeblendet, nachdem Ihre Bedingung erfüllt ist.

Wie Sie sehen können, setzen wir .ng-hide-animate auf hidden. Dies ist der Grund für die Verzögerung, da auf den Abschluss der Animation gewartet wird. Sie können Ihrem Hide-Ereignis eine Animation hinzufügen, wie der Klassenname impliziert, anstatt sie wie im obigen Beispiel auszublenden.

Palvinder
quelle
1
Ich hatte eine einfache Seite mit nur ein paar ng-if, ng-showdie sichtbar langsam war. Ich habe es entfernt ngAnimateund es hat das Problem für mich behoben. Vielen Dank!
Eamonn Gahan
1
Dies löste ein Problem, das ich auch hatte ... Wissen Sie, warum das Vorhandensein von ngAnimate den langsamen Übergang verursachte?
Clark
Hatte das gleiche Problem - das Entfernen von ngAnimate hat es gelöst .. aber das ist nicht gut .. viele Module benötigen ngAnimate, um coole Animationen zu machen .. was zu tun ist? ngAnimattias wo bist du? :)
Spock
20
Im Fall von ng-ifhat das Hinzufügen nur .ng-leave { display:none; }zum Element den Trick für mich getan ( !importantwurde nicht benötigt).
Joao
40

Ich hatte das gleiche Problem und habe es umgangen, indem ich ng-class mit dem Klassennamen 'hidden' verwendet habe, um das Element auszublenden, anstatt ng-if oder ng-show / ng-hide zu verwenden.

Neimad
quelle
1
Scheint mit Animationen und / oder Ereignishandlern verbunden zu sein. Ich bin mir nicht sicher, warum die anderen langsam sind, aber ich würde gerne wissen
Thiago Festa
1
wie kannst du das tun?
jsmedmar
Das geht so viel schneller! Warum ist das??
Aron
1
Ich würde denken, dass dies einfach auf die Tatsache zurückzuführen ist, dass die Verwendung von ngAnimate das Verhalten von Ein- / Ausstiegsanimationen auf Elemente anwendet, die ng-if / ng-show verwenden, während dies bei Änderungen der Ausdrücke der ng-Klasse nicht der Fall ist.
John Rix
@neimad wie geht das? In meinem Fall muss ich ng-if verwenden, um zu testen, ob ein Eigenschaftswert vorliegt null(der einige Sekunden auf den API-Aufruf wartet), sodass zwei ausgewählte Elemente kurz angezeigt werden. Also benutzt du überhaupt nicht ng-if ? Vielen Dank.
Chris22
15

Ich habe hier einige Lösungen gefunden , aber das Beste für mich war, das Styling für die .ng-animate-Klasse zu überschreiben:

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

Dies ist ein Beispiel: http://jsfiddle.net/9krLr/27/

Ich hoffe dir zu helfen.

Ruben Perez
quelle
9

Ich hatte ein ähnliches Problem. Ich habe die $scope.$evalAsync()Aktualisierung der Bindung erzwungen.

Es wirkt wie ein Zauber.

Vermeiden Sie die Verwendung, $scope.$applyda dies zu Konflikten mit einer bereits laufenden $ Digest-Phase führen kann.

if(selectedStatistics.length === 0 || selectedWorkgroups.length === 0){
    ctrl.isSaveDisabled = true;
    $scope.$evalAsync();
} else{
    ctrl.isSaveDisabled = false;
    $scope.$evalAsync();
}
rach8garg
quelle
Hat für mich gearbeitet. Aber hat es irgendwelche Nachteile?
Sarah Tammam
1
Ich habe keine angetroffen. Es ist sehr praktisch bei asynchronen Operationen.
Rach8garg
1
Vielen Dank für die hilfreiche Antwort :)
Sarah Tammam
1

Ich hatte das gleiche Problem bei der Verwendung

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

In meinem Fall habe ich es durch Hinzufügen einer Klasse gelöst:

.hidden {
  display: none;
}

und dann die Klasse bedingt hinzufügen, anstatt zu verwenden *ngIf:

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

Wenn immer es auf diese Weise verwendet wird , würde ich prüfen , die Umbenennung shouldShowzu shouldHide(und die Logik , dass Abtretungs es negieren), so kann es als verwendet werden , shouldHidestatt !shouldShow.

Wenn Sie display: flexin Ihrem CSS die vorhandene Klasse des DIV haben, hat diese Anzeigeeigenschaft möglicherweise Vorrang vor der display: hidden. display: none !importantStattdessen kann eine einfache Lösung verwendet werden. Oft gibt es jedoch bessere Lösungen, um auf andere Weise Vorrang zu haben. Hier finden Sie eine gute Lektüre über Alternativen .

Kent Munthe Caspersen
quelle
0

In der Winkelversion 1.5.x ist das Hinzufügen $scope.$apply()nach der Änderung der Bedingung, die für mich erledigt wurde, eine Beispielfunktion

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


        }
mohamed
quelle