如何在正确的时间 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);
}
});
编辑:从答案看来使用超时(即使延迟为 0)是一种常见做法,但问题仍然是这是否会保证 selection 在 Angular 完成更新文本后发生。
为此,您可以使用延迟为 0 的 $timeout。
$timeout(function(){
document.querySelector("input").setSelectionRange(0, 4);
});
Angular在下一个$digest
循环中改变DOM,速度非常快,但不会在运行 [=12]时立即可用=].在这种情况下,通常我们会使用 $timeout
到 "wait"。
如果您不想使用 $timeout
,您可以使用 ng-blur
触发事件。当元素失去焦点时会触发模糊事件。
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 只会在更新后发生。
我有一个输入框。当文本更改时,我需要 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);
}
});
编辑:从答案看来使用超时(即使延迟为 0)是一种常见做法,但问题仍然是这是否会保证 selection 在 Angular 完成更新文本后发生。
为此,您可以使用延迟为 0 的 $timeout。
$timeout(function(){
document.querySelector("input").setSelectionRange(0, 4);
});
Angular在下一个$digest
循环中改变DOM,速度非常快,但不会在运行 [=12]时立即可用=].在这种情况下,通常我们会使用 $timeout
到 "wait"。
如果您不想使用 $timeout
,您可以使用 ng-blur
触发事件。当元素失去焦点时会触发模糊事件。
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 只会在更新后发生。