kątowe ng-if lub ng-show reaguje wolno (2-sekundowe opóźnienie?)

87

Próbuję pokazać lub ukryć wskaźnik ładowania na przycisku, gdy żądanie jest zajęte. Robię to z angular, zmieniając zmienną $ scope.loading podczas ładowania żądania lub po zakończeniu ładowania.

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

        })
        .error(function(error){

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

Na froncie:

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

Działa to dobrze, ale ikona ładowania (odświeżanie jonów) jest wyświetlana przez około 2 sekundy, podczas gdy zmienna $ scope jest aktualizowana natychmiast. Próbowałem użyć $ scope. $ Apply, ale to nie wygląda na to, co jest nie tak, zakres jest aktualizowany dobrze i natychmiast po żądaniu. To tylko ikona, która nie reaguje wystarczająco szybko.

Dzięki za pomoc w zrozumieniu tego!

Jorre
źródło
2
Czy są jakieś animacje?
tasseKATT
Negatywny. Brak animacji. Zamiast tego wydaje się pomagać używanie ng-class.
Jorre
Mam ten sam lub podobny problem. Zakres jest aktualizowany natychmiast i poprawnie - zweryfikowałem to logując komunikaty z $scopefunkcji, które ng-ifużywają, aby dowiedzieć się, czy odpowiednie elementy powinny zostać wyświetlone. Jednak przyciski z ng-ifpozostają przez chwilę nieprawidłowo widoczne lub ukryte. Następnie po krótkiej chwili wszystkie przyciski przyjmują swój zamierzony widoczny / ukryty stan. - Obejrzałem to, używając ng-hidezamiast tego. Wersja kątowa 1.2.16.
KajMagnus
Jakieś rozwiązanie dla tych, którzy nie używają animacji?
Zia Ul Rehman Mughal

Odpowiedzi:

124

Spróbuj usunąć ngAnimate, jeśli nie używasz go z konfiguracji aplikacji i strony index.html:

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

@Spock; jeśli nadal potrzebujesz ngAnimate, pozostaw konfigurację aplikacji nietkniętą i po prostu dodaj następujący CSS:

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

Spowoduje to ukrycie animowanej ikony zaraz po spełnieniu twojego warunku.

Jak widać, ustawiamy .ng-hide-animate na ukryty. To właśnie powoduje opóźnienie w oczekiwaniu na zakończenie animacji. Możesz dodać animację do swojego zdarzenia hide, jak sugeruje nazwa klasy, zamiast ją ukrywać, jak w powyższym przykładzie.

Palvinder
źródło
1
Miałem prostą stronę z tylko kilkoma stronami ng-if, ng-showktóra była widocznie powolna. Usunąłem ngAnimatei rozwiązałem problem. Dzięki!
Eamonn Gahan
1
To rozwiązało problem, który też miałem ... Czy wiesz, dlaczego obecność ngAnimate powodowała powolne przejście?
Clark,
Miałem ten sam problem - usunięcie ngAnimate rozwiązało go… ale to nie jest dobre… wiele modułów potrzebuje ngAnimate do robienia fajnych animacji… co robić? ngAnimattias, gdzie jesteś? :)
Spock
21
W przypadku ng-ifdodania tylko .ng-leave { display:none; }do elementu załatwiło mi sprawę ( !importantnie było potrzebne).
Joao,
40

Miałem ten sam problem i obejść go, używając ng-class z `` ukrytą '' nazwą klasy, aby ukryć element, zamiast używać ng-if lub ng-show / ng-hide.

neimad
źródło
1
Wydaje się związane z animacjami i / lub programami obsługi zdarzeń. Nie bardzo wiem, dlaczego inni są powolni, ale chciałbym wiedzieć
Thiago Festa
1
Jak możesz to robić?
jsmedmar
To jest o wiele szybsze! Dlaczego to??
Aron
1
Myślę, że wynika to po prostu z faktu, że użycie ngAnimate stosuje zachowania animacji wejścia / wyjścia do elementów używających ng-if / ng-show, podczas gdy nie robi tego w przypadku zmian w wyrażeniach ng-class.
John Rix,
@neimad jak to się robi? W moim przypadku muszę użyć ng-if, aby sprawdzić, czy wartość właściwości jest null(czyli przez kilka sekund czeka na wywołanie interfejsu API), więc dwa wybrane elementy są wyświetlane na krótko. Więc ng-if w ogóle nie używasz ? Dzięki.
Chris22
15

Znalazłem tutaj kilka rozwiązań , ale dla mnie najlepsze było nadpisanie stylizacji dla klasy .ng-animate:

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

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

To jest przykład: http://jsfiddle.net/9krLr/27/

Mam nadzieję, że ci pomogę.

Ruben Perez
źródło
10

Miałem podobny problem, $scope.$evalAsync()wymuszałem aktualizację wiązania.

To działa jak urok.

Unikaj używania, $scope.$applyponieważ może to powodować konflikt z już uruchomioną fazą podsumowania $.

if(selectedStatistics.length === 0 || selectedWorkgroups.length === 0){
    ctrl.isSaveDisabled = true;
    $scope.$evalAsync();
} else{
    ctrl.isSaveDisabled = false;
    $scope.$evalAsync();
}
rach8garg
źródło
Pracował dla mnie. Ale czy ma jakieś wady?
Sarah Tammam
1
Nie spotkałem żadnego. Jest to bardzo przydatne w przypadku operacji asynchronicznych.
rach8garg,
1
Dziękuję za pomocną odpowiedź :)
Sarah Tammam
Ta odpowiedź wydaje się być jackpotem, dzięki.
Abdeali Chandanwala
Nawiasem mówiąc, ten opóźniony problem występuje głównie w środowisku lokalnego hosta i rzadko w produkcji - nie wiem dlaczego
Abdeali Chandanwala
1

Miałem ten sam problem podczas używania

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

W moim przypadku rozwiązałem to dodając klasę:

.hidden {
  display: none;
}

a następnie warunkowe dodanie klasy zamiast używania *ngIf:

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

Jeśli zawsze używam go w ten sposób, rozważałbym zmianę nazwy shouldShowna shouldHide(i zanegowanie logiki, która go przypisuje), więc może być używany jako shouldHidezamiast !shouldShow.

Jeśli masz display: flexw swoim CSS istniejącą klasę DIV, ta właściwość wyświetlania może mieć pierwszeństwo przed display: hidden. display: none !importantZamiast tego można użyć łatwej poprawki , ale często istnieją lepsze rozwiązania zapewniające pierwszeństwo na inne sposoby. Oto dobra lektura o alternatywach .

Kent Munthe Caspersen
źródło
0

w wersji kątowej 1.5.x dodawanie $scope.$apply()po zmianie stanu wykonałem zadanie u mnie tu przykładowa funkcja

$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
źródło