AngularJs - UI中的字段不反映更新的模型值
AngularJs - field in UI not reflecting updated model value
这是Plunkr
一个常见的场景,我有一个在ng-repeat中显示的项集合。对于显示的每一行,我都有一个启动流程(文件上传)的按钮和一个状态字段。我希望我的UI能够反映流程状态的变化。这在Angular的双向绑定中应该很容易,对吧?
我在ng-repeat上创建了第二个(子)控制器,这样我就可以简单地在它自己的范围内更新项的状态,而不是处理项的集合,特别是因为这个过程是异步的,用户可能会并发地上传许多文件。
问题:我对Ang/JS中的$scope的理解是缺乏的-哈哈。但是,当范围模型值更新时,UI中的绑定{{xxx}}值不会更新。单击任何一个按钮并查看警报。如何让UI正确更新?
供参考-在现实中,按钮调用外部库的API来上传文件,并返回给我一个url来检查我上传的状态。然后在setInterval()循环中轮询url以ping状态,直到完成或出现错误。我已经简化了普朗克的这一部分,因为这种复杂性本身不是问题所在。Plunkr
<!DOCTYPE html>
<html ng-app="myapp">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js@1.2.x" src="http://code.angularjs.org/1.2.7/angular.js" data-semver="1.2.7"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<table>
<th></th>
<th>Id</th>
<th>Name</th>
<th>Status</th>
<tr ng-repeat="item in items" ng-controller="ChildCtrl">
<td><button ng-click="updateStatus(item)">click</button></td>
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.status}}</td>
</tr>
</table>
</body>
</html>
JS
var app = angular.module('myapp', []);
app.controller('MainCtrl', function($scope) {
$scope.items = [ {id: 1, name: "Moe", status: "init"}
, {id: 3, name: "Larry", status: "init"}
, {id: 2, name: "Curly", status: "init"}
];
});
app.controller('ChildCtrl', function($scope) {
$scope.updateStatus = function(item){
$scope.myItem = item;
alert('child: ' + item.id + ' status: ' + item.status);
item.status = 'clicked';
alert('status just update in UI to: ' + item.status);
callResult = fakeAjaxCall($scope);
alert('callResult: ' + callResult);
};
var fakeAjaxCall = function(scope){
setTimeout(function (item) {
if (-1 == -1) { //success
result = "Wow, it worked!";
alert('current status: ' + scope.myItem.status);
alert('ajax result: ' + result);
scope.myItem.status = result;
alert('new status: ' + scope.myItem.status);
alert("but the status in the UI didn't update");
}
}, 2000);
};
});
你需要使用$timeout而不是setTimeout
来从angular中调用更新模态的摘要周期,或者你必须自己调用摘要周期(通过包装代码scope.$apply()
, scope.evalAsync
等),原因是angular不知道setTimeout
何时完成,因为它没有发生在angular中。当你有一种有角度的方式来做事情,并且你可以自由地使用它时,你应该尽量不要手动调用摘要循环。在这种情况下,你可以用$timeout
替换setTimeout
,模型的变化将自动反映在视图中,因为当$timeout
完成时,angular会调用一个摘要周期。另一个优点是,当使用$timeout
时,它也会返回一个承诺,您可以将其链接起来,并且与setTimeout
相反,仍然可以实现承诺模式。
app.controller('ChildCtrl', function($scope, $timeout) {
$scope.updateStatus = function(item){
$scope.myItem = item;
console.log('child: ' + item.id + ' status: ' + item.status);
item.status = 'clicked';
console.log('status now updates in UI to: ' + item.status);
callResult = fakeAjaxCall($scope);
console.log('callResult: ' + callResult);
};
var fakeAjaxCall = function(scope){
$timeout(function (item) {
if (-1 == -1) { //success
result = "Wow, it worked!";
console.log('current status: ' + scope.myItem.status);
console.log('ajax result: ' + result);
scope.myItem.status = result;
console.log('new status: ' + scope.myItem.status);
console.log("but the status in the UI doesn't update");
}
}, 2000);
};
Plnkr
在调试异步操作时,我建议使用console.log(或$log
)而不是alert进行调试。
当你在angular之外改变作用域变量时,比如在超时回调中,你可以告诉angular使用$scope.$apply来更新摘要循环。
var fakeAjaxCall = function(scope){
setTimeout(function (item) {
if (-1 == -1) { //success
result = "Wow, it worked!";
alert('current status: ' + scope.myItem.status);
alert('ajax result: ' + result);
scope.$apply(scope.myItem.status = result); // <---- Changed
alert('new status: ' + scope.myItem.status);
alert("but the status in the UI doesn't update");
}
}, 2000);
};
您需要使用$timeout
。
setTimeout
将该值从angularjs的作用域中移除。而您可以使用scope.$apply()
手动更新范围。最好使用angular预构建的包装器。
美元超时更新Plunkr
app.controller('ChildCtrl', function($scope,$timeout) {
$scope.updateStatus = function(item){
$scope.myItem = item;
alert('child: ' + item.id + ' status: ' + item.status);
item.status = 'clicked';
alert('status now updates in UI to: ' + item.status);
callResult = fakeAjaxCall($scope);
alert('callResult: ' + callResult);
};
var fakeAjaxCall = function(scope){
$timeout(function (item) {
if (-1 == -1) { //success
result = "Wow, it worked!";
alert('current status: ' + scope.myItem.status);
alert('ajax result: ' + result);
$scope.myItem.status = result;
alert('new status: ' + scope.myItem.status);
alert("but the status in the UI doesn't update");
}
}, 2000);
};
});
- 视图ngValue-Angular JS中未更新模型的更改
- 需要使用触摸屏从 AngularJS 指令中更新模型
- 角度指令没有更新模型视图
- 复选框仅在第二次单击后更新模型
- Angular.js-Socket.io事件更新模型,而不是视图
- UI Select在删除后不会更新模型
- 为什么ng提交没有提交和更新模型
- AngularJS-基于URL更新模型
- 视图更改时,Ember.js更新模型
- Knockoutjs函数更新模型时应出现异常
- 挖空绑定不会更新模型
- 范围不更新模型中的更改
- 导航时更新模型变量
- 角度.js更新模型
- Ember.js不更新模型
- 在使用挖空自定义绑定时更新模型时更新元素
- 在自我更新时以ng重复更新模型
- 如何在主干中对列表进行排序时更新模型的顺序属性
- AngularJS 复选框不更新模型
- 更新模型中的数据不会绑定到控制器