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

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

我有一个输入框。当文本更改时,我需要 select 文本。我知道有很多事情正在进行,我需要等待它们完成。我设置了超时,它起作用了。但是我不想依赖一个固定的时间。当 Angular 完成更改文本时,有什么方法可以 select 文本吗?

示例HTML:

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

示例 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.

编辑:从答案看来使用超时(即使延迟为 0)是一种常见做法,但问题仍然是这是否会保证 selection 在 Angular 完成更新文本后发生。

为此,您可以使用延迟为 0 的 $timeout。

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

Angular在下一个$digest循环中改变DOM,速度非常快,但不会在运行 [=12]时立即可用=].在这种情况下,通常我们会使用 $timeout 到 "wait"。

如果您不想使用 $timeout,您可以使用 ng-blur 触发事件。当元素失去焦点时会触发模糊事件。

Working fiddle

HTML:

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

脚本:

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

$timeout 0 延迟实际上足够好,因为 angular 的脏检查(和 $digest 循环)是同步发生的。 (0 延迟只会在当前进程空闲时触发)。

如果你真的很想保证,方法如下:

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

您必须使用超时来包装 $apply,因为作用域函数会触发 $digest,并且您不能在 $digest 周期内调用 $digest($apply 为您调用 $digest)。 $apply 此处保证范围变量已更新,因此您的 setSelectionRange 只会在更新后发生。