【问题标题】:Angularjs: how to make input[text] ngModel delay valued while typing [duplicate]Angularjs:如何在输入[重复]时使输入[文本] ngModel延迟值
【发布时间】:2013-08-05 03:15:56
【问题描述】:

我有一个带有ngModel 绑定的文本框,如下所示:

<input type="text" ng-model="typing" />

这个texbox的值

value: {{ typing }}

我希望模型延迟在我输入时更新值。也许如果我在 500 毫秒内停止输入,模型将更新所有值(我在文本框中输入的所有内容)。 我做了一些谷歌,但没有运气。任何人有任何想法吗?请帮忙。

编辑

这个Angularjs: input[text] ngChange fires while the value is changing 没有为我的情况提供解决方案。它在模糊后带来解决方案更新值,但我希望在停止输入后更新值,而不是模糊文本框。

编辑 2(答案)

对于 Angular 版本 1.4,指令 ngModelOptions 在我的情况下很有用。我可以这样写<input ng-model="typing" ng-model-options="{ updateOn: 'default', debounce: {'default': 500, 'blur': 0} }" /> 来延迟更新值到模型默认 500 毫秒,如果失去焦点立即更新。

【问题讨论】:

  • 那个解决方案绑定事件blur,所以当你blur的时候,值会被更新。但是在这里,我希望它在停止输入后更新,而不是从文本框中模糊。
  • 在此处查看此答案,它提供了一个指令,允许您延迟 ng-change:stackoverflow.com/questions/21121460/…。您可以使用 ngChange 以 500 毫秒的 ngDelay 更新模型。

标签: javascript angularjs


【解决方案1】:

处理这个问题的最简洁的方法可能是编写一个指令来包装<input> 元素并添加延迟行为。这是我为相同目的编写的指令:

angular.module('MyModule')
    .directive('easedInput', function($timeout) {
        return {
            restrict: 'E',
            template: '<div><input class="{{externalClass}} my-eased-input" type="text" ng-model="currentInputValue" ng-change="update()" placeholder="{{placeholder}}"/></div>',
            scope: {
                value: '=',
                timeout: '@',
                placeholder: '@',
                externalClass: '@class'
            },
            transclude: true,
            link: function ($scope) {
                $scope.timeout = parseInt($scope.timeout);
                $scope.update = function () {
                    if ($scope.pendingPromise) { $timeout.cancel($scope.pendingPromise); }
                    $scope.pendingPromise = $timeout(function () { 
                        $scope.value = $scope.currentInputValue;
                    }, $scope.timeout);
                };
            }
        }
    });

这个指令会像这样在你的 HTML 中被调用:

<eased-input value="myValue" timeout="500" placeholder="Please enter text..." />

剖析指令:

超时服务

该指令使用 Angular 的 $timeout 服务来处理计时:它是调用 setTimeout 的可注入、可模拟、惯用的替代方案。该服务被注入到指令构造函数中。

属性

该指令接受三个属性:valuetimeoutplaceholder

这里的value 属性绑定到拥有封闭“上下文”的控制器范围内的变量。在这种情况下,它绑定到myValue,即绑定到负责此代码的任何控制器上的$scope.myValue。它具有双向绑定,由指令的scope 属性中的'=' 条目表示。这意味着当该指令更新value 时,更改会传播到拥有该指令的控制器;因此,$scope.myValue 将在指令内更改 value 时更改。

timeoutplaceholder 属性具有单向绑定:指令从属性中读取它们的值,但不会改变它们。它们实际上是配置值。

HTML 模板

指令上的template 属性显示了一旦Angular 编译并链接它就会在其位置生成的HTML。它基本上只是一个input 元素,具有一些特殊且不那么特殊的属性。输入框中的值通过ng-model 绑定到指令的$scope 上的currentInputValue 变量。输入框上的change 事件通过ng-change 指令绑定到指令的$scope 上的update 函数。

链接功能

该过程的核心在于指令上的link 函数:我们定义了一个update 方法。如上所述,此方法绑定到指令的 HTML 模板中输入框的change 事件。因此,每次用户更改框中的输入时,都会调用update

此方法使用$timeout 服务。它告诉$timeout 服务等待timeout 毫秒,然后应用设置$scope.value = $scope.currentInputValue 的回调。这类似于调用setTimeout(function () {$scope.value = $scope.currentInputValue}, timeout)

$timeout 调用返回一个承诺。我们可以通过调用$timeout.cancel(p) 取消由$timeout 生成的承诺p,该承诺正在等待执行。这就是update 在第一行中所做的:如果我们有来自先前更改事件的承诺,我们会在创建新事件之前取消它。这意味着如果我们有例如500 毫秒超时,更新被调用两次,调用相隔 400 毫秒,我们将只有一个等待触发的承诺。

总体结果

承诺在解决时设置$scope.value = currentInputValue;即,它将“外部可见”value 属性设置为具有输入框内容的值。 value 只会改变 - 外部控制器只会看到 value 改变 - 在timeout 毫秒的静止期之后,我相信这是你所追求的行为。

【讨论】:

    【解决方案2】:

    如果您对模型中的第二个属性感到满意,您可以将$scope.$watchdebounce 函数一起使用:

    HTML

    <input type="text" ng-model="typing" />
    <input type="text" value="{{ typed }}" />
    

    Javascript

    $scope.$watch('typing', debounce(function() {
        $scope.typed = $scope.typing;
        $scope.$apply();
    }, 500));
    

    您可以编写自己的去抖动函数,或使用现有的。 here 有一个很好的实现,或者,如果你碰巧使用了 undescore.js,you're already set

    这是一个jsFiddle 示例。

    更新:Angular 1.3 现在有一个内置的方法来消除用户输入的抖动:ngModelOptions

    【讨论】:

    • 不错。代理救援。 :) +1
    • 不错的一个。但我注意到了一些事情:如果我设置第二个字段,第二个字段“失去”绑定。要在您的小提琴中重现,请在第一个中写一些东西,然后在第二个中,然后再在第一个中。这是一个错误还是只是一些奇怪的行为?
    • @RaphaelMüller 不错的收获。我不知道为什么会这样。如果您检查标记,您将看到第二个输入的 value 属性设置正确。不过,我应该改用ng-model。无论如何,在 Angular 1.3 中没有必要做任何事情,因为框架现在有一个内置的解决方案来解决这个问题。
    • @MichaelBenford 谢谢,明天我会看看这个新选项。我希望这就是我正在寻找的,没有肮脏的黑客等等。
    • Angular 1.3 的新模型选项是我一直在寻找的。它们让生活更轻松。
    猜你喜欢
    • 2015-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-25
    • 1970-01-01
    • 2014-01-27
    相关资源
    最近更新 更多