angular ng-if или ng-show медленно реагирует (задержка 2 секунды?)

87

Я пытаюсь показать или скрыть индикатор загрузки на кнопке, когда запрос занят. Я делаю это с помощью angular, изменяя переменную $ scope.loading, когда запрос загружается или когда он загружается.

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

        })
        .error(function(error){

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

В интерфейсе:

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

Это работает нормально, но значок загрузки (ионное обновление) отображается около 2 секунд, а переменная $ scope обновляется немедленно. Я попробовал $ scope. $ Apply, но, похоже, что здесь не так, область обновляется сразу после запроса. Просто значок не реагирует достаточно быстро.

Спасибо, что помогли мне понять это!

Хорре
источник
2
Есть какие-нибудь анимации?
tasseKATT
Отрицательный. Никаких анимаций. Вместо этого использование ng-class кажется полезным.
Jorre
У меня такая же или похожая проблема. Область действия обновляется немедленно и правильно - я проверил это, зарегистрировав сообщения от $scopeфункций, которые ng-ifиспользуются, чтобы узнать, должны ли отображаться соответствующие элементы. Тем не менее, кнопки ng-ifостаются неправильно видимыми или скрытыми в течение некоторой секунды. Затем через короткое время все кнопки принимают предполагаемое видимое / скрытое состояние. - Я работал над этим, используя ng-hideвместо этого. Угловая версия 1.2.16.
KajMagnus
Любое решение для тех, кто не использует анимацию?
Зия Уль Рехман Могол

Ответы:

124

Попробуйте удалить ngAnimate, если вы не используете его из конфигурации вашего приложения и страницы index.html:

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

@Spock; если вам все еще требуется использование ngAnimate, оставьте конфигурацию приложения нетронутой и просто добавьте следующий CSS:

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

Это скроет анимированный значок сразу после выполнения вашего условия.

Как видите, мы устанавливаем .ng-hide-animate как скрытый. Это то, что вызывает задержку при ожидании завершения анимации. Вы можете добавить анимацию к вашему событию скрытия, как следует из названия класса, вместо того, чтобы скрывать ее, как в примере выше.

Palvinder
источник
1
У меня была простая страница всего с парочкой ng-if, ng-showкоторая была заметно медленной. Я удалил, ngAnimateи это устранило проблему. Благодарность!
Eamonn Gahan
1
Это решило мою проблему ... Вы знаете, почему присутствие ngAnimate вызывает медленный переход?
Clark
Была та же проблема - удаление ngAnimate решило ее .. но это нехорошо .. многим модулям нужен ngAnimate для создания крутых анимаций .. что делать? ngAnimattias где ты? :)
Spock
21
В случае с ng-ifдобавлением только .ng-leave { display:none; }элемента помогло мне ( !importantне было необходимости).
Joao
40

У меня была такая же проблема, и я решил ее обойти, используя ng-class со «скрытым» именем класса, чтобы скрыть элемент вместо использования ng-if или ng-show / ng-hide.

Neimad
источник
1
Кажется, связано с анимацией и / или обработчиками событий. Не совсем уверен, почему другие медленные, но я хотел бы знать
Тьяго Феста
1
как ты можешь это сделать?
jsmedmar
Это намного быстрее! Почему это??
Aron
1
Я бы подумал, что это просто связано с тем, что использование ngAnimate применяет поведение анимации входа / выхода к элементам, использующим ng-if / ng-show, в то время как он не делает этого для изменений в выражениях класса ng.
Джон Рикс
@neimad, как это делается? В моем случае мне нужно использовать ng-if, чтобы проверить, есть ли значение свойства null(которое на пару секунд ждет вызова api), поэтому на короткое время отображаются два элемента select. Так ты вообще не пользуешься ng-if ? Спасибо.
Chris22
15

Я нашел несколько решений здесь , но лучшим для меня было переопределение стиля для класса .ng-animate:

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

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

Это пример: http://jsfiddle.net/9krLr/27/

Надеюсь помочь вам.

Рубен Перес
источник
10

У меня возникла аналогичная проблема, я использовал $scope.$evalAsync()принудительное обновление привязки.

Работает как часы.

Избегайте использования, так $scope.$applyкак это может конфликтовать с уже запущенной фазой дайджеста.

if(selectedStatistics.length === 0 || selectedWorkgroups.length === 0){
    ctrl.isSaveDisabled = true;
    $scope.$evalAsync();
} else{
    ctrl.isSaveDisabled = false;
    $scope.$evalAsync();
}
rach8garg
источник
Работал у меня. Но есть ли у него недостатки?
Сара Таммам
1
Я не встречал ни одного. Это очень удобно в случае асинхронных операций.
rach8garg
1
Спасибо за полезный ответ :)
Сара Таммам
Этот ответ кажется джекпотом, спасибо.
Абдеали Чанданвала,
Между прочим, эта отложенная проблема в основном происходит в среде localhost и редко в производстве - не знаю почему
Абдели Чанданвала
1

У меня была такая же проблема при использовании

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

В моем случае я решил это, добавив класс:

.hidden {
  display: none;
}

а затем условно добавив класс вместо использования *ngIf:

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

Если всегда использовать его таким образом, я бы подумал о переименовании shouldShowв shouldHide(и отрицаю логику, которая его назначает), поэтому его можно использовать как shouldHideвместо!shouldShow .

Если у вас есть display: flexCSS для существующего класса DIV, это свойство display может иметь приоритет над display: hidden. display: none !importantВместо этого можно использовать простое исправление , но часто есть более эффективные решения для обеспечения приоритета другими способами. Вот хорошее чтение об альтернативах .

Кент Мунте Касперсен
источник
0

в angular версии 1.5.x добавление $scope.$apply()после изменения условия выполнило эту работу для меня вот пример функции

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


        }
Мохамед
источник