Angular ng-change delay


117

ฉันมีอินพุตที่กรองรายการ ng-repeat เกี่ยวกับการเปลี่ยนแปลง การทำซ้ำมีข้อมูลจำนวนมากและใช้เวลาสองสามวินาทีในการกรองทุกอย่าง ฉันต้องการให้พวกเขาหน่วงเวลา 0.5 วินาทีก่อนที่ฉันจะเริ่มกระบวนการกรอง อะไรคือวิธีที่ถูกต้องในเชิงมุมในการสร้างความล่าช้านี้?

อินพุต

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

ทำซ้ำ

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

ฟังก์ชั่นตัวกรอง

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

ขอบคุณ


1
เพียงแค่ใช้$timeout500ms $scope.FilterByName = function () { $timeout(_filterByName , 500)
PSL

@PSL อยู่ที่ไหนในฟังก์ชั่น? ฉันต้องการให้การค้นหาดำเนินการเพียงครั้งเดียว ถ้าฉันหักล้างมันก็จะยิ่งสร้างความล่าช้ามากขึ้นและทำการค้นหาหลายครั้ง
MGot90

ใช่ในหน้าที่ของคุณ ความคิดเห็นก่อนหน้ามีตัวอย่าง คุณสามารถใช้ได้$timeout.cancel(timeoutpromise)หากอยู่ระหว่างการหมดเวลาและการเปลี่ยนแปลงอื่นจะถูกทริกเกอร์
PSL


1
@PSL ขอบคุณที่ทำงานอย่างมีเสน่ห์!
MGot90

คำตอบ:


274

AngularJS 1.3+

เนื่องจาก AngularJS 1.3 คุณสามารถใช้debounceคุณสมบัติที่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);
        };
    }
]);

-- หรือ --

ตรวจสอบ Fiddle

ก่อน AngularJS 1.3

คุณจะต้องใช้ $ timeout เพื่อเพิ่มการหน่วงเวลาและอาจด้วยการใช้ $ timeout.cancel (previoustimeout) คุณสามารถยกเลิกการหมดเวลาก่อนหน้านี้และเรียกใช้การหมดเวลาใหม่ได้ (ช่วยป้องกันไม่ให้มีการดำเนินการกรองหลาย ๆ ครั้งภายใน a ช่วงเวลา)

นี่คือตัวอย่าง:

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
โปรดทราบว่าng-model-optionsถูกเพิ่มในAngular v1.3 เท่านั้น (และคุณสมบัติ debounce ในเบต้า 8 ) บรรดาผู้ที่ยังคงต้องใช้รุ่นเก่าของเชิงมุมจะต้องรีสอร์ทเพื่อแก้ปัญหาอื่น ๆ เช่นหนึ่งจาก PSL หรือโดยใช้โมดูลภายนอกเช่นNG-debounce
Vincent Sels

ข้อเสียอาจเป็นไปได้ว่าจะทำให้การตรวจสอบล่าช้าเช่น ng-pattern ล่าช้าเช่นกัน
Johan Baaij

19

คุณสามารถใช้$timeoutเพื่อเพิ่มการหน่วงเวลาและอาจด้วยการใช้$timeout.cancel(previoustimeout)คุณสามารถยกเลิกการหมดเวลาก่อนหน้านี้และเรียกใช้การหมดเวลาใหม่ได้ (ช่วยป้องกันไม่ให้มีการดำเนินการกรองหลาย ๆ ครั้งภายในช่วงเวลาหนึ่ง)

ตัวอย่าง:-

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
สำหรับผู้ลงคะแนนและผู้เยี่ยมชมในอนาคต: คำตอบนี้ถูกเพิ่มสำหรับAngular 1.2.xและอาจเพิ่มก่อน 1.3.x ซึ่งมีตัวเลือก debounce พร้อมตัวเลือก ng-model และไม่เคยมีโอกาสแก้ไขคำตอบก่อนที่จะดีกว่า คำตอบจาก @rckd เข้ามา (ประมาณ 3 เดือนหลังจากนี้)
PSL

4
แม้ว่าฉันจะใช้ angular js 1.4 ฉันก็ยังพบว่าโซลูชัน $ timeout มีประโยชน์ng-changeเมื่อฉันไม่ต้องการหักล้างโมเดล
SStanley

8

ฉันรู้ว่าคำถามเก่าเกินไป แต่ก็ยังคงต้องการที่จะให้หนึ่งในวิธีที่รวดเร็วเพื่อให้บรรลุนี้โดยใช้debouncing

ดังนั้นโค้ดสามารถเขียนเป็นไฟล์

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

Debounce จะใช้ตัวเลขเป็นมิลลิวินาที


0

หรือคุณสามารถใช้คำสั่ง 'typeahead-wait-ms = "1000"' จาก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">
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.