Hom*_*man 25 angularjs angularjs-directive
我有一个搜索输入字段,其中包含与ng-change绑定的requery函数.
<input ng-model="search" ng-change="updateSearch()">
Run Code Online (Sandbox Code Playgroud)
然而,这对每个角色来说都会过快.所以我最终做了类似的事情:
$scope.updateSearch = function(){
$timeout.cancel(searchDelay);
searchDelay = $timeout(function(){
$scope.requery($scope.search);
},300);
}
Run Code Online (Sandbox Code Playgroud)
因此,请求仅在用户停止输入后300ms进行.是否有任何解决方案将其包装在指令中?
sch*_*max 50
从角度1.3开始,使用ngModelOptions更容易实现:
<input ng-model="search" ng-change="updateSearch()" ng-model-options="{debounce:3000}">
Syntax: {debounce: Miliseconds}
Run Code Online (Sandbox Code Playgroud)
Dou*_*oug 25
为了解决这个问题,我创建了一个名为ngDelay的指令.
ngDelay增强了ngChange的行为以支持所需的延迟行为,该行为在用户处于非活动状态时提供更新,而不是在每次击键时提供.诀窍是使用子范围,并将ngChange的值替换为包含超时逻辑的函数调用,并在父范围上执行原始表达式.第二个技巧是将任何ngModel绑定移动到父作用域(如果存在).这些更改都在ngDelay指令的编译阶段执行.
这是一个小提琴,其中包含一个使用ngDelay的例子:http: //jsfiddle.net/ZfrTX/7/(由我编写和编辑,在mainguy和Ryan Q的帮助下)
你可以在GitHub上找到这个代码,感谢brentvatne.谢谢布伦特!
为了快速参考,这里是ngDelay指令的JavaScript:
app.directive('ngDelay', ['$timeout', function ($timeout) {
return {
restrict: 'A',
scope: true,
compile: function (element, attributes) {
var expression = attributes['ngChange'];
if (!expression)
return;
var ngModel = attributes['ngModel'];
if (ngModel) attributes['ngModel'] = '$parent.' + ngModel;
attributes['ngChange'] = '$$delay.execute()';
return {
post: function (scope, element, attributes) {
scope.$$delay = {
expression: expression,
delay: scope.$eval(attributes['ngDelay']),
execute: function () {
var state = scope.$$delay;
state.then = Date.now();
$timeout(function () {
if (Date.now() - state.then >= state.delay)
scope.$parent.$eval(expression);
}, state.delay);
}
};
}
}
}
};
}]);
Run Code Online (Sandbox Code Playgroud)
如果有任何TypeScript游戏,这里是使用DefinitelyTyped的角度定义的TypeScript:
components.directive('ngDelay', ['$timeout', ($timeout: ng.ITimeoutService) => {
var directive: ng.IDirective = {
restrict: 'A',
scope: true,
compile: (element: ng.IAugmentedJQuery, attributes: ng.IAttributes) => {
var expression = attributes['ngChange'];
if (!expression)
return;
var ngModel = attributes['ngModel'];
if (ngModel) attributes['ngModel'] = '$parent.' + ngModel;
attributes['ngChange'] = '$$delay.execute()';
return {
post: (scope: IDelayScope, element: ng.IAugmentedJQuery, attributes: ng.IAttributes) => {
scope.$$delay = {
expression: <string>expression,
delay: <number>scope.$eval(attributes['ngDelay']),
execute: function () {
var state = scope.$$delay;
state.then = Date.now();
$timeout(function () {
if (Date.now() - state.then >= state.delay)
scope.$parent.$eval(expression);
}, state.delay);
}
};
}
}
}
};
return directive;
}]);
interface IDelayScope extends ng.IScope {
$$delay: IDelayState;
}
interface IDelayState {
delay: number;
expression: string;
execute(): void;
then?: number;
action?: ng.IPromise<any>;
}
Run Code Online (Sandbox Code Playgroud)
这对我来说非常有效:JSFiddle
var app = angular.module('app', []);
app.directive('delaySearch', function ($timeout) {
return {
restrict: 'EA',
template: ' <input ng-model="search" ng-change="modelChanged()">',
link: function ($scope, element, attrs) {
$scope.modelChanged = function () {
$timeout(function () {
if ($scope.lastSearch != $scope.search) {
if ($scope.delayedMethod) {
$scope.lastSearch = $scope.search;
$scope.delayedMethod({ search: $scope.search });
}
}
}, 300);
}
},
scope: {
delayedMethod:'&'
}
}
});
Run Code Online (Sandbox Code Playgroud)
使用指令
在你的控制器中:
app.controller('ctrl', function ($scope,$timeout) {
$scope.requery = function (search) {
console.log(search);
}
});
Run Code Online (Sandbox Code Playgroud)
在您看来:
<div ng-app="app">
<div ng-controller="ctrl">
<delay-search delayed-method="requery(search)"></delay-search>
</div>
</div>
Run Code Online (Sandbox Code Playgroud)