Açısal ng-değişim gecikmesi


117

Değişiklik durumunda ng-tekrar listesini filtreleyen bir girişim var. Yineleme çok fazla veri içerir ve her şeyi filtrelemek birkaç saniye sürer. Filtreleme işlemine başlamadan önce 0,5 saniyelik gecikme olmasını istiyorum. Bu gecikmeyi yaratmanın doğru açısal yolu nedir?

Giriş

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

Tekrar et

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

Filtre Fonksiyonu

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

Teşekkürler


1
$timeout500ms için a kullanın . $scope.FilterByName = function () { $timeout(_filterByName , 500)
PSL

@PSL işlevin neresinde? Aramanın yalnızca bir kez yapılmasını istiyorum. Sadece dengelersem, daha büyük bir gecikme yaratacak ve birden fazla arama yapacaktır.
MGot90

Evet, işlevinde. prev yorumun bir pasajı var. Sen kullanabilirsiniz $timeout.cancel(timeoutpromise)tek zaman aşımı devam ediyor ve başka değişiklik tetiklenen alırsa.
PSL


1
@PSL Teşekkürler bir cazibe gibi çalışıyor!
MGot90

Yanıtlar:


274

AngularJS 1.3+

AngularJS 1.3 sayesinde, hiç kullanmadan bunu çok kolay bir şekilde gerçekleştirmenizi sağlayan debounceözellikten yararlanabilirsiniz . İşte bir örnek:ngModelOptions$timeout

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

- VEYA -

Fiddle'ı kontrol edin

AngularJS 1.3'ten önce

Bir gecikme eklemek için $ timeout kullanmanız gerekecek ve muhtemelen $ timeout.cancel (previoustimeout) kullanarak önceki herhangi bir zaman aşımını iptal edebilir ve yenisini çalıştırabilirsiniz (filtrelemenin bir Zaman aralığı)

İşte bir örnek:

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
Bunun ng-model-optionsyalnızca Angular v1.3'te (ve beta.8'de geri alma özelliğinin) eklendiğini unutmayın . Angular'ın daha eski bir sürümünü kullanmaya ihtiyaç duyanlar, PSL'deki gibi veya ng-debounce gibi harici bir modül kullanarak başka çözümlere başvurmak zorunda kalacaklar .
Vincent Sels

Bunun bir dezavantajı, bunun ng-pattern gibi doğrulamaları da geciktirmesi olabilir.
Johan Baaij

19

Sen kullanabilirsiniz $timeoutkullanımı ile muhtemelen bir gecikme ve eklenecek $timeout.cancel(previoustimeout)yenisini daha önceki zaman aşımı iptal edip çalıştırabilirsiniz size (bir zaman aralığı içinde consecutovely yürütülecek birden çok kez filtreleme önlemeye yardımcı olur)

Misal:-

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
Olumsuz oy verene ve gelecekteki ziyaretçilere: Bu cevap Angular 1.2.x için eklendi ve muhtemelen ng-model-seçenekleriyle geri çevirme seçeneğine sahip olan ve cevabı daha iyi bir şekilde gözden geçirme şansı bulamayan 1.3.x yayınlanmadan önce eklendi. @ rckd'den yanıt geldi (bundan yaklaşık 3 ay sonra).
PSL

4
Açısal js 1.4 kullanmama rağmen ng-change, modeli geri çevirmek istemediğimde hala $ zaman aşımı çözümünü kullanışlı buluyorum .
SStanley

8

Sorunun çok eski olduğunu biliyorum. Ancak yine de, debouncing kullanarak bunu başarmanın daha hızlı bir yolunu sağlamak istiyoruz .

Böylece kod şu şekilde yazılabilir:

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

Geri tepme, sayıyı milisaniye olarak alacaktır.


0

veya angular-ui'den 'typeahead-wait-ms = "1000"' yönergesini kullanabilirsiniz.

<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">
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.