Winkel-ng-Änderungsverzögerung

117

Ich habe eine Eingabe, die eine ng-Wiederholungsliste bei Änderung filtert. Die Wiederholung enthält viele Daten und dauert einige Sekunden, um alles zu filtern. Ich möchte eine Verzögerung von 0,5 Sekunden, bevor ich mit dem Filtervorgang beginne. Was ist der richtige Weg im Winkel, um diese Verzögerung zu erzeugen?

Eingang

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

Wiederholen

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

Filterfunktion

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

Vielen Dank

MGot90
quelle
1
Verwenden Sie einfach eine $timeoutfür 500ms. $scope.FilterByName = function () { $timeout(_filterByName , 500)
PSL
@PSL wo in der Funktion? Ich möchte, dass die Suche nur einmal ausgeführt wird. Wenn ich es nur versetze, wird es nur eine größere Verzögerung verursachen und mehrere Suchen durchführen.
MGot90
Ja, in deiner Funktion. Der vorherige Kommentar hat einen Ausschnitt. Sie können verwenden, $timeout.cancel(timeoutpromise)wenn eine Zeitüberschreitung ausgeführt wird und eine weitere Änderung ausgelöst wird.
PSL
1
@PSL Danke funktioniert wie ein Zauber!
MGot90

Antworten:

273

AngularJS 1.3+

Seit AngularJS 1.3 können Sie die debounceEigenschaft nutzen ngModelOptions, um dies sehr einfach ohne Verwendung zu erreichen$timeout überhaupt zu verwenden. Hier ist ein Beispiel:

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

-- ODER --

Überprüfen Sie die Geige

Vor AngularJS 1.3

Sie müssen $ timeout verwenden, um eine Verzögerung hinzuzufügen, und wahrscheinlich können Sie mit $ timeout.cancel (previoustimeout) jedes vorherige Timeout abbrechen und das neue ausführen (dies verhindert, dass die Filterung innerhalb von a mehrmals hintereinander ausgeführt wird Zeitintervall)

Hier ist ein Beispiel:

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
quelle
2
Beachten Sie, dass dies ng-model-optionsnur in Angular v1.3 (und der Debounce-Eigenschaft in Beta.8 ) hinzugefügt wurde . Diejenigen, die noch eine ältere Version von Angular verwenden müssen, müssen auf andere Lösungen wie die von PSL oder ein externes Modul wie ng-debounce zurückgreifen .
Vincent Sels
Ein Nachteil könnte sein, dass dies auch Validierungen wie das ng-Muster zu verzögern scheint.
Johan Baaij
19

Sie könnten verwenden $timeout, um eine Verzögerung hinzuzufügen und wahrscheinlich mit der Verwendung von$timeout.cancel(previoustimeout) Option eine frühere Zeitüberschreitung abbrechen und die neue ausführen (dies verhindert, dass die Filterung innerhalb eines Zeitintervalls mehrmals hintereinander ausgeführt wird).

Beispiel:-

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
quelle
8
An den Downvoter und zukünftige Besucher: Diese Antwort wurde für Angular 1.2.x hinzugefügt und wahrscheinlich vor der Veröffentlichung von 1.3.x hinzugefügt. Diese hat die Debounce-Option mit ng-model-Optionen und hatte nie die Möglichkeit, die Antwort vor einer besseren zu überarbeiten Die Antwort von @rckd kam herein (ungefähr 3 Monate nach dieser).
PSL
4
Obwohl ich Angular JS 1.4 verwende, finde ich die $ timeout-Lösung immer noch nützlich, ng-changewenn ich das Modell nicht entprellen möchte.
SStanley
8

Ich weiß, dass die Frage zu alt ist. Aber ich möchte immer noch einen schnelleren Weg bieten, um dies durch Entprellen zu erreichen .

So kann der Code geschrieben werden als

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

Bei der Entprellung wird die Zahl in Millisekunden angegeben.

Naibedya Kar
quelle
0

oder Sie können die Direktive 'typeahead-wait-ms = "1000"' von angle -ui verwenden

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