Kątowe opóźnienie zmiany ng

117

Mam dane wejściowe, które filtrują listę powtórzeń ng po zmianie. Powtórzenie zawiera dużo danych i przefiltrowanie wszystkiego zajmuje kilka sekund. Chciałbym, aby były opóźnione o 0,5 sekundy przed rozpoczęciem procesu filtrowania. Jaki jest prawidłowy sposób w kątowym, aby utworzyć to opóźnienie?

Wejście

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

Powtarzać

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

Funkcja filtra

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

Dzięki

MGot90
źródło
1
Po prostu użyj $timeoutprzez 500 ms. $scope.FilterByName = function () { $timeout(_filterByName , 500)
PSL
@PSL gdzie w funkcji? Chcę, aby wyszukiwanie zostało wykonane tylko raz. Jeśli to zrównoważy, po prostu utworzy większe opóźnienie i przeprowadzi wiele wyszukiwań.
MGot90
Tak, w twojej funkcji. poprzedni komentarz zawiera fragment. Możesz użyć, $timeout.cancel(timeoutpromise)jeśli trwa jeden limit czasu, a inna zmiana zostanie wyzwolona.
PSL
1
@PSL Dziękuję działa jak urok!
MGot90

Odpowiedzi:

273

AngularJS 1.3+

Od AngularJS 1.3 możesz wykorzystać tę debouncewłaściwość, ngModelOptionsaby osiągnąć to bardzo łatwo, bez użycia $timeoutw ogóle. Oto przykład:

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);
        };
    }
]);

- LUB -

Sprawdź skrzypce

Przed AngularJS 1.3

Będziesz musiał użyć $ timeout, aby dodać opóźnienie i prawdopodobnie za pomocą $ timeout.cancel (previoustimeout) możesz anulować poprzedni limit czasu i uruchomić nowy (pomaga to zapobiec wielokrotnemu wykonywaniu filtrowania w ciągu Przedział czasowy)

Oto przykład:

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
źródło
2
Zauważ, że ng-model-optionszostało dodane tylko w Angular v1.3 (i właściwość debounce w wersji beta.8 ). Ci, którzy nadal będą musieli korzystać ze starszej wersji Angulara, będą musieli skorzystać z innych rozwiązań, na przykład z PSL, lub z zewnętrznego modułu, takiego jak ng-debounce .
Vincent zostaje sprzedany
Wadą może być to, że wydaje się, że opóźnia to również walidację, podobnie jak wzór ng.
Johan Baaij
19

Możesz użyć, $timeoutaby dodać opóźnienie i prawdopodobnie za pomocą $timeout.cancel(previoustimeout)ciebie możesz anulować poprzedni limit czasu i uruchomić nowy (pomaga zapobiec wielokrotnemu wykonywaniu filtrowania w odstępach czasu)

Przykład:-

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
źródło
8
Do zwolenników i przyszłych gości: Ta odpowiedź została dodana dla Angular 1.2.xi dodana prawdopodobnie przed wydaniem 1.3.x, który ma opcję debounce z ng-model-options i nigdy nie miał szansy na poprawienie odpowiedzi przed lepszą nadeszła odpowiedź od @rckd (około 3 miesiące po tej).
PSL
4
Mimo że używam angular js 1.4, nadal uważam, że rozwiązanie $ timeout jest przydatne, ng-changegdy nie chcę usuwać modelu.
SStanley
8

Wiem, że to pytanie jest zbyt stare. Ale nadal chcę zapewnić jeden szybszy sposób osiągnięcia tego za pomocą odbicia .

Więc kod można zapisać jako

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

Odbicie przyjmie liczbę w milisekundach.

Naibedya Kar
źródło
0

lub możesz użyć dyrektywy 'typeahead-wait-ms = "1000"' z 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">
Vadym Kaptan
źródło