Угловая задержка изменения ng

117

У меня есть вход, который фильтрует список ng-repeat при изменении. Повторение содержит много данных и требует нескольких секунд, чтобы отфильтровать все. Я бы хотел, чтобы у них была задержка 0,5 секунды, прежде чем я начну процесс фильтрации. Как правильно создать эту задержку в angular?

вход

 <input ng-model="xyz" ng-change="FilterByName()" />

Повторение

 <div ng-repeat"foo in bar">
      <p>{{foo.bar}}</p>
 </div>

Функция фильтра

 $scope.FilterByName = function () {
      //Filtering Stuff Here
 });

Спасибо

MGot90
источник
1
Просто используйте $timeoutдля 500 мс. $scope.FilterByName = function () { $timeout(_filterByName , 500)
PSL
@PSL где в функции? Я хочу, чтобы поиск выполнялся только один раз. Если я просто компенсирую это, это просто создаст большую задержку и выполнит несколько поисков.
MGot90
Ага, в твоей функции. у предыдущего комментария есть отрывок. Вы можете использовать, $timeout.cancel(timeoutpromise)если один тайм-аут выполняется и запускается другое изменение.
PSL
1
@PSL Спасибо, работает как шарм!
MGot90

Ответы:

274

AngularJS 1.3+

Начиная с AngularJS 1.3, вы можете использовать debounceсвойство ngModelOptionsпредоставляет, чтобы добиться этого очень просто, $timeoutвообще не используя . Вот пример:

HTML:

<div ng-app='app' ng-controller='Ctrl'>
    <input type='text' placeholder='Type a name..'
        ng-model='vm.name'
        ng-model-options='{ debounce: 1000 }'
        ng-change='vm.greet()'
    />

    <p ng-bind='vm.greeting'></p>
</div>

JS:

angular.module('app', [])
.controller('Ctrl', [
    '$scope',
    '$log',
    function($scope, $log){
        var vm = $scope.vm = {};

        vm.name = '';
        vm.greeting = '';
        vm.greet = function greet(){
            vm.greeting = vm.name ? 'Hey, ' + vm.name + '!' : '';
            $log.info(vm.greeting);
        };
    }
]);

-- ИЛИ --

Проверьте скрипку

До AngularJS 1.3

Вам нужно будет использовать $ timeout, чтобы добавить задержку, и, вероятно, с помощью $ timeout.cancel (previoustimeout) вы можете отменить любой предыдущий тайм-аут и запустить новый (помогает предотвратить многократное выполнение фильтрации в течение временной интервал)

Вот пример:

app.controller('MainCtrl', function($scope, $timeout) {
    var _timeout;

    //...
    //...

    $scope.FilterByName = function() {
        if(_timeout) { // if there is already a timeout in process cancel it
            $timeout.cancel(_timeout);
        }
        _timeout = $timeout(function() {
            console.log('filtering');
            _timeout = null;
        }, 500);
    }
});
rckd
источник
2
Обратите внимание, что это ng-model-optionsбыло добавлено только в Angular v1.3 (и свойство debounce в beta.8 ). Тем, кому все еще нужно использовать старую версию Angular, придется прибегнуть к другим решениям, например, от PSL, или с помощью внешнего модуля, такого как ng-debounce .
Винсент Селс
Обратной стороной может быть то, что это, похоже, также задерживает проверки, такие как ng-pattern.
Johan Baaij
19

Вы можете использовать $timeoutдля добавления задержки и, вероятно, с ее помощью $timeout.cancel(previoustimeout)вы можете отменить любой предыдущий тайм-аут и запустить новый (помогает предотвратить выполнение фильтрации несколько раз подряд в течение определенного интервала времени)

Пример:-

app.controller('MainCtrl', function($scope, $timeout) {
  var _timeout;

 //...
 //...

  $scope.FilterByName = function () {
    if(_timeout){ //if there is already a timeout in process cancel it
      $timeout.cancel(_timeout);
    }
    _timeout = $timeout(function(){
      console.log('filtering');
      _timeout = null;
    },500);
  }
 });

Plnkr

PSL
источник
8
Тем, кто проголосовал против и будущим посетителям: этот ответ был добавлен для Angular 1.2.x и добавлен, вероятно, до того, как был выпущен 1.3.x, в котором есть опция debounce с ng-model-options и никогда не было возможности пересмотреть ответ до того, как пришел ответ от @rckd (примерно через 3 месяца после этого).
PSL
4
Несмотря на то, что я использую angular js 1.4, я все же считаю решение $ timeout полезным, ng-changeкогда я не хочу отклонять модель.
SStanley
8

Я знаю, что вопрос слишком старый. Но все же хочу предоставить один более быстрый способ добиться этого с помощью противодействия .

Таким образом, код можно записать как

<input ng-model="xyz" ng-change="FilterByName()" ng-model-options="{debounce: 500}"/>

Debounce будет принимать число в миллисекундах.

Наибедья Кар
источник
0

или вы можете использовать директиву typeahead-wait-ms = "1000" 'из angular-ui

<input 
   typeahead="name for name in filterWasChanged()"
   typeahead-wait-ms="1000"
   type="text" placeholder="search"
   class="form-control" style="text-align: right" 
   ng-model="templates.model.filters.name">
Вадим Каптан
источник