Retraso de cambio angular ng

117

Tengo una entrada que filtra una lista de repetición ng al cambiar. La repetición contiene una gran cantidad de datos y tarda unos segundos en filtrarse por todo. Me gustaría que tuvieran un retraso de 0,5 segundos antes de comenzar el proceso de filtrado. ¿Cuál es la forma correcta en angular para crear este retraso?

Entrada

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

Repetir

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

Función de filtro

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

Gracias

MGot90
fuente
1
Solo use un $timeoutpara 500ms. $scope.FilterByName = function () { $timeout(_filterByName , 500)
PSL
@PSL ¿en qué parte de la función? Solo quiero que la búsqueda se ejecute una vez. Si lo compensé, creará un retraso mayor y hará varias búsquedas.
MGot90
Sí, en tu función. El comentario anterior tiene un fragmento. Puede utilizarlo $timeout.cancel(timeoutpromise)si hay un tiempo de espera en curso y se activa otro cambio.
PSL
1
@PSL Gracias funciona como un encanto!
MGot90

Respuestas:

273

AngularJS 1.3+

Desde AngularJS 1.3, puede utilizar la debouncepropiedad que ngModelOptionsproporciona para lograrlo muy fácilmente sin usar $timeouten absoluto. He aquí un ejemplo:

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 -

Revisa el violín

Antes de AngularJS 1.3

Tendrá que usar $ timeout para agregar un retraso y probablemente con el uso de $ timeout.cancel (previoustimeout) puede cancelar cualquier tiempo de espera anterior y ejecutar el nuevo (ayuda a evitar que el filtrado se ejecute varias veces consecutivas dentro de un intervalo de tiempo)

Aquí hay un ejemplo:

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
fuente
2
Tenga en cuenta que ng-model-optionssolo se agregó en Angular v1.3 (y la propiedad antirrebote en beta.8 ). Aquellos que todavía necesiten usar una versión anterior de Angular deberán recurrir a otras soluciones, como la de PSL, o mediante el uso de un módulo externo como ng-debounce .
Vincent Sels
Una desventaja podría ser que esto también parece retrasar validaciones como ng-pattern.
Johan Baaij
19

Puede usar $timeoutpara agregar un retraso y probablemente con el uso de $timeout.cancel(previoustimeout)puede cancelar cualquier tiempo de espera anterior y ejecutar el nuevo (ayuda a evitar que el filtrado se ejecute varias veces consecutivas dentro de un intervalo de tiempo)

Ejemplo:-

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
fuente
8
Para el votante negativo y los futuros visitantes: esta respuesta se agregó para Angular 1.2.x , y probablemente se agregó antes de que se lanzara 1.3.x, que tiene la opción de rebote con ng-model-options y nunca tuvo la oportunidad de revisar la respuesta antes de una mejor llegó la respuesta de @rckd (alrededor de 3 meses después de esta).
PSL
4
Aunque estoy usando angular js 1.4, todavía encuentro útil la solución $ timeout ng-changecuando no quiero eliminar el rebote del modelo.
SStanley
8

Sé que la pregunta es demasiado antigua. Pero aún quiero proporcionar una forma más rápida de lograr esto mediante la eliminación de rebotes .

Entonces el código se puede escribir como

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

Debounce tomará el número en milisegundos.

Naibedya Kar
fuente
0

o puede usar la directiva 'typeahead-wait-ms = "1000"' de 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
fuente