- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个包含动态输入数量的表单,由 AngularJS 控制。
<body ng-app="mainApp" ng-controller="CreatePollController" ng-init="init(3)">
<form id="createPollForm">
<input class="create-input" ng-repeat="n in questions" id="q_{{$index}}" name="q_{{$index}}" type="text" ng-keypress="createInputKeypress($event);"/>
<a href="javascript:void(0);" ng-click="addQuestion()">Add Question</a>
</form>
</body>
这是由以下 Angular 代码控制的:
app.controller('CreatePollController', function($scope) {
$scope.questions = [];
$scope.init = function(numOfInputs){
for(var i = 0; i < numOfInputs; i++){
$scope.questions.push({
"questionText":""
});
}
};
$scope.addQuestion = function(){
$scope.questions.push({
"questionText":""
});
};
$scope.createInputKeypress = function(e){
if(e.keyCode === 13){
e.preventDefault();
var idx = Number(e.target.id.replace("q_", ""));
if(idx === this.questions.length - 1){
this.addQuestion();
}
// Wait for angular update ????
var nextId = "#q_" + (++idx);
$(nextId).focus();
}
};
});
目前,当用户在关注文本输入时按下 Enter 键时,会调用 createInputKeypress 函数,浏览器会关注表单中的下一个输入。但是,如果您当前专注于表单中的最后一个元素,它会向 questions
数组添加一个新问题,这将导致在 DOM 中生成另一个输入。
但是,当创建这个新元素时,focus() 调用不起作用。我怀疑这是因为 angular 没有立即添加新元素,所以尝试使用 jQuery 定位和聚焦新元素不起作用。
有没有办法等待 DOM 更新,然后聚焦新元素?
最佳答案
您可能已经知道,javascript 是基于轮流的,这意味着浏览器将轮流(循环)执行 JS 代码。目前,在下一个 javascript 周期中准备回调的方法是使用我们希望在超时中在下一个周期运行的代码设置回调,我们可以通过调用 setTimeout
来实现。以 0
毫秒为间隔,这将强制在下一个 javascript 轮次中调用给定的回调,在浏览器完成(从) 当前的回调之后。
为了保持简单,一个浏览器周期按给定顺序执行这些操作:
看看这个例子:
console.log(1);
console.log(2);
setTimeout(function () {
console.log(3);
console.log(4);
}, 0);
console.log(5);
console.log(6);
/** prints in the console
* 1 - in the current JS turn
* 2 - in the current JS turn
* 5 - in the current JS turn
* 6 - in the current JS turn
* 3 - in the next JS turn
* 4 - in the next JS turn
**/
3和4打印在5和6之后,即使知道没有间隔 (0
) 在 setTimeout
中,因为 setTimeout
基本上准备给定回调,仅在当前 javascript 轮次完成后调用。如果在下一回合,当前时间与setTimeout
指令绑定(bind)回调的时间差小于setTimeout
传入的时间间隔,则回调不会被调用,它会等待下一个回合,重复这个过程,直到时间间隔小于那个差值,然后才调用回调!
由于 AngularJS 是一个包装我们所有代码的框架, Angular 更新通常发生在我们的代码执行之后,在每个 javascript 轮次结束时,这意味着对 HTML 的 Angular 更改只会发生在当前的 javascript 回合结束。
AngularJS 也有一个内置的超时服务,叫做 $timeout
, difference between the native setTimeout
and angular's $timeout
service最后一个是服务函数,它恰好调用原生的 setTimeout
和一个 angular 的内部回调,这个回调又负责执行我们传入的回调 $timeout
然后确保我们在 $scope
中所做的任何更改都将反射(reflect)在其他地方!然而,由于在我们的例子中我们实际上并不想更新 $scope
,我们不需要使用这个服务,一个简单的 setTimeout
恰好更有效!
了解所有这些信息后,我们可以使用 setTimeout
来解决我们的问题。像这样:
$scope.createInputKeypress = function(e){
if(e.keyCode === 13){
e.preventDefault();
var idx = Number(e.target.id.replace("q_", ""));
if(idx === this.questions.length - 1){
this.addQuestion();
}
// Wait for the next javascript turn
setTimeout(function () {
var nextId = "#q_" + (++idx);
$(nextId).focus();
}, 0);
}
};
为了让它更语义化,我们可以包装setTimeout
逻辑在具有更多上下文化名称的函数中,例如 runAfterRender
:
function runAfterRender (callback) {
setTimeout(function () {
if (angular.isFunction(callback)) {
callback();
}
}, 0);
}
现在我们可以使用这个函数来准备下一个 javascript 轮次的代码执行:
app.controller('CreatePollController', function($scope) {
// functions
function runAfterRender (callback) {
setTimeout(function () {
if (angular.isFunction(callback)) {
callback();
}
}, 0);
}
// $scope
$scope.questions = [];
$scope.init = function(numOfInputs){
for(var i = 0; i < numOfInputs; i++){
$scope.questions.push({
"questionText":""
});
}
};
$scope.addQuestion = function(){
$scope.questions.push({
"questionText":""
});
};
$scope.createInputKeypress = function(e){
if(e.keyCode === 13){
e.preventDefault();
var idx = Number(e.target.id.replace("q_", ""));
if(idx === this.questions.length - 1){
this.addQuestion();
}
runAfterRender(function () {
var nextId = "#q_" + (++idx);
$(nextId).focus();
});
}
};
});
关于javascript - 我如何在 AngularJS 中创建和聚焦新元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45803620/
我正在用 Java 编写代码,并且使用 Vaadin 8 扩展。 我有一个 Vaadin 组合盒,效果很好。但我不仅想从组合框中选择项目,还想选择书面输入。这意味着我想使用组合框作为下拉菜单以及文本编
我正在尝试将 AJAX 添加到 JQuery ListView 中并呈黄色闪烁,但我似乎无法使其正常工作。谁能指出我正确的方向? http://jsfiddle.net/zFybm/ 最佳答案 根据
我有这个样式表: .pixel{ position: absolute; height: 10px; width: 10px; background-color: #f
这是我用来将新行推送到容器的一行代码: this.$el.append(new ItemView(item).render().el); 其中item是Backbone.js model,render
我正在尝试在 anguar.js 中制作一些测试应用程序,但遇到了问题。我的 js 文件包含: live = angular.module('live',[]); live.controller('p
如何绑定(bind)页面加载后创建的新元素? 我有这样的东西 system = function() { this.hello = function() { alert
html5 新元素(页眉、导航、页脚等)在 IE 中不工作 最佳答案 您需要包含 HTML5 shiv 脚本以允许在旧版 IE 浏览器中设置 HTML5 元素的样式:http://code.googl
我是一名优秀的程序员,十分优秀!