Ritardo di cambio angolare


117

Ho un input che filtra un elenco di ripetizioni al cambiamento. La ripetizione contiene molti dati e impiega alcuni secondi per filtrare tutto. Vorrei che ci fossero 0,5 secondi di ritardo prima di iniziare il processo di filtraggio. Qual è il modo corretto in angolare per creare questo ritardo?

Ingresso

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

Ripetere

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

Funzione di filtro

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

Grazie


1
Usa solo a $timeoutper 500 ms. $scope.FilterByName = function () { $timeout(_filterByName , 500)
PSL

@PSL dove nella funzione? Voglio che la ricerca venga eseguita una sola volta. Se lo compenso, creerà solo un ritardo maggiore ed eseguirà più ricerche.
MGot90

Sì, nella tua funzione. Il commento precedente ha uno snippet. È possibile utilizzarlo $timeout.cancel(timeoutpromise)se è in corso un timeout e viene attivata un'altra modifica.
PSL


1
@PSL Grazie funziona come un incantesimo!
MGot90

Risposte:


274

AngularJS 1.3+

A partire da AngularJS 1.3 puoi utilizzare la debounceproprietà ngModelOptionsfornisce per ottenere ciò molto facilmente senza usare $timeoutaffatto. Ecco un esempio:

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

-- O --

Controlla il violino

Prima di AngularJS 1.3

Dovrai usare $ timeout per aggiungere un ritardo e probabilmente con l'uso di $ timeout.cancel (previoustimeout) puoi annullare qualsiasi timeout precedente ed eseguire quello nuovo (aiuta a evitare che il filtro venga eseguito più volte consecutivamente all'interno di un Intervallo di tempo)

Ecco un esempio:

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

2
Nota che è ng-model-optionsstato aggiunto solo in Angular v1.3 (e la proprietà debounce in beta.8 ). Chi ha ancora bisogno di utilizzare una vecchia versione di Angular dovrà ricorrere ad altre soluzioni, come quella di PSL, oppure utilizzando un modulo esterno come ng-debounce .
Vincent Sels

Uno svantaggio potrebbe essere che questo sembra ritardare anche convalide come ng-pattern.
Johan Baaij

19

Potresti usare $timeoutper aggiungere un ritardo e probabilmente con l'uso di $timeout.cancel(previoustimeout)puoi annullare qualsiasi timeout precedente ed eseguire quello nuovo (aiuta a evitare che il filtraggio venga eseguito più volte consecutivamente entro un intervallo di tempo)

Esempio:-

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


8
Per il downvoter e per i futuri visitatori: questa risposta è stata aggiunta per Angular 1.2.xe probabilmente prima del rilascio di 1.3.x che ha l'opzione debounce con ng-model-options e non ha mai avuto la possibilità di rivedere la risposta prima di una migliore la risposta di @rckd è arrivata (circa 3 mesi dopo questa).
PSL

4
Anche se sto usando angular js 1.4, trovo ancora utile la soluzione $ timeout ng-change quando non voglio eseguire il debounce del modello.
SStanley

8

So che la domanda è troppo vecchia. Ma voglio comunque fornire un modo più rapido per raggiungere questo obiettivo utilizzando il debouncing .

Quindi il codice può essere scritto come

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

Debounce prenderà il numero in millisecondi.


0

oppure puoi usare la direttiva 'typeahead-wait-ms = "1000"' da 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">
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.