角度变化延迟


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 2014年

@PSL在函数中的哪里?我只希望搜索执行一次。如果仅抵消它,它将造成更大的延迟并进行多次搜索。
MGot90

是的,在您的职务上。上一条评论有一个摘要。$timeout.cancel(timeoutpromise)如果一个超时正在进行,并且触发了另一个更改,则可以使用。
PSL 2014年


1
@PSL谢谢您的努力!
MGot90

Answers:


273

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

- 要么 -

检查小提琴

在AngularJS 1.3之前

您必须使用$ 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);
    }
});

2
请注意,该功能ng-model-options仅在Angular v1.3中添加(以及beta.8中的debounce属性)。那些仍然需要使用较旧版本的Angular的用户将不得不求助于其他解决方案,例如PSL的解决方案,或者使用ng-debounce这样的外部模块。
文森特·塞尔斯

不利的一面是,这似乎也延迟了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);
  }
 });

普伦克


8
给下级投票者和未来的访问者:这个答案是为Angular 1.2.x添加的,可能是在1.3.x发布之前添加的,它具有带有ng-model-options的debounce选项,并且从来没有机会在更好的情况下修改答案来自@rckd的答案来了(大约一个月后3个月)。
PSL

4
即使我使用的是angular js 1.4,ng-change当我不想对模型进行反跳处理时,我仍然发现$ timeout解决方案很有用。
SStanley,2016年

8

我知道这个问题太老了。但是仍然想提供一种更快的方法来使用反跳来实现。

所以代码可以写成

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

去抖动将以毫秒为单位。


0

或者您可以使用angular-ui中的指令'typeahead-wait-ms =“ 1000”'

<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">
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.