简体   繁体   English

在正确的时间更改Angular后,如何选择输入中的文本?

[英]How to select text in an input after a change in Angular at the right time?

I have an input box. 我有一个输入框。 When the text changes, I need to select the text. 当文本更改时,我需要选择文本。 I understand that there are many events going on and I need to wait for them to finish. 我知道发生了许多事件,我需要等待它们完成。 I put in a timeout and it works. 我设置了超时,它可以正常工作。 However I don't want to rely on a constant time. 但是我不想依赖固定的时间。 Is there any way how to select the text when Angular is finished changing the text? Angular完成更改文本后,有什么方法可以选择文本?

Example HTML: HTML示例:

<input type="text" value="{{txt}}">
<button ng-click="select()">Press</button>

Example JS: JS示例:

angular.module('MyApp', []).controller('MyCtrl', function ($scope, $interval) {
    $scope.txt = "Hello World";
    $scope.select = function () {
        $scope.txt = "Bye World";
        // doesn't work, too early
        document.querySelector("input").setSelectionRange(0, 4);
        // works
        $interval(function () {
            document.querySelector("input").setSelectionRange(0, 4);
        }, 10, 1);
    }
});

Working example is JSFiddle. 工作示例是JSFiddle。

EDIT : From the answers it looks like using timeouts (even with 0 delay) is a common practice, but the question remains whether this will guarantee that the selection happens after Angular finishes updating the text. 编辑 :从答案看来,使用超时(即使延迟为0)是一种常见做法,但是问题仍然在于,这是否可以保证选择在Angular完成更新文本后发生。

You can use $timeout with 0 delay for this purpose. 为此,您可以将$ timeout与0延迟一起使用。

$timeout(function(){
    document.querySelector("input").setSelectionRange(0, 4); 
});

Angular changes the DOM in next $digest cycle, it is extremely fast, but it won't be available as soon as you run $scope.x = ?? Angular在下一个$digest周期中更改DOM,它的速度非常快,但是在运行$scope.x = ??后将不可用。 . Normally we would use $timeout to "wait" in this case. 通常,在这种情况下,我们将使用$timeout来“等待”。

$timeout 0 delay is in fact good enough since angular's dirty checking (and $digest cycle) happens synchronously. 实际上,由于角度的脏检查(和$ digest循环)是同步发生的,因此$ timeout 0延迟已经足够了。 (0 delay would only fire up when the current process is free). (仅当当前进程空闲时才触发0延迟)。

If you really really want to guarantee it, here's how: 如果您真的要保证,请按照以下步骤操作:

angular.module('MyApp', []).controller('MyCtrl', function ($scope, $timeout) {
    $scope.txt = "Hello World";
    $scope.select = function () {
        $timeout(function () {
            $scope.$apply(function () {
                $scope.txt = "Bye World";
            });
            document.querySelector("input").setSelectionRange(0, 4);
        });
    };
});

You have to use timeout to wrap the $apply, because the scope function would trigger a $digest and you cannot call $digest within a $digest cycle($apply calls $digest for you). 您必须使用超时来包装$ apply,因为范围函数会触发$ digest,并且您不能在$ digest周期内调用$ digest($ apply为您调用$ digest)。 $apply here guarantee the scope variable is updated, hence your setSelectionRange would only happen after the update. $ apply在此处保证范围变量已更新,因此您的setSelectionRange仅在更新后发生。

If you do not want to use $timeout , you can fire event with ng-blur . 如果您不想使用$timeout ,则可以使用ng-blur触发事件。 A blur event fires when an element has lost focus. 当元素失去焦点时会触发模糊事件。

Working fiddle 工作提琴

HTML: HTML:

    <div ng-controller="MyCtrl">
        <form>
            <input type="text" ng-blur="select()" value="{{txt}}">
            <button>Press</button>
        </form>
    </div>

Script: 脚本:

angular.module('MyApp', []).controller('MyCtrl', function ($scope, $interval) {       
    $scope.select = function () {    
        document.querySelector("input").setSelectionRange(0, 4);
    }
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM