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


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

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


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.


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">
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.