我正在编写一个应用程序,用户可以升级使用游戏币支付的组件。按下“升级”按钮后,会向服务器发送ajax请求并升级组件。之后,我发出另一个ajax请求来检索新的组件页面。但是,当数据更新时,不会再次检查ng-disabled,因此升级按钮在不应该的情况下仍然可以点击。重新加载页面或路由修复此问题。但重新加载页面并不是一个好的用户体验。
我正在做这个项目来学习Angularjs方式,所以如果我的设置有什么问题或者我做了什么,请告诉我!
我尝试包含所有相关代码,如果缺少某些内容,您可以使用用户和密码“test”在this link下查看。
对于headstart,在machine-overview.html
按钮调用upgradeComponent
控制器controller.js
中的MachineOverviewCtrl
发出Ajax请求并成功更新$scope.user
和{{1}更改的数据会反映在视图($scope.machine
)中,但不评估按钮ng-repeat
并保持旧状态。
我做错了什么?我如何强制进行评估或以Angularjs喜欢的方式进行更新?
修改
@ jack.the.ripper的答案是缺少这一点,即有多个按钮,每个按钮重复一次,但这些按钮只是不评估他们的ng-disable指令。
//修改
ng-disabled
<!DOCTYPE html>
<html lang="de" ng-app="hacksApp">
<head>
<!--ommited includes (angularjs, bootstrap etc)-->
</head>
<body ng-controller="hacksUserCtrl">
<!--ommited navbar-->
<div ng-view></div>
</body>
</html>
javascript vars及其起源:
<!--ommited divs-->
<table class="table table-bordered">
<!--ommited thead-->
<tbody>
<tr ng-repeat="component in machine | object2Array | orderBy:'ComponentID'"><!--converting objects to arrays, issue appears with and without filter-->
<!--ommited other irrelevant td-->
<td>
<button
ng-disabled="
{{
(component.price_next <= 0) || (component.price_next > user.values.euro) ||
(user.values.energy_remaining < (component.energy_next-component.energy))
}}"
ng-click="upgradeComponent(component)" class="btn btn-danger" role="button">
Upgrade {{component.text}} for <span class="glyphicon glyphicon-euro"></span> {{component.price_next}}
</button>
</td>
</tr>
</tbody>
</table>
<!--ommited divs-->
$scope.user.x //hacksUserCtrl
$scope.machine.x //MachineOverviewCtrl
var hacksApp = angular.module('hacksApp', [
'ngRoute',
'hacksControllers',
'hacksFilters',
]);
hacksApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/machine', {
templateUrl: 'html/machine-overview.html',
controller: 'MachineOverviewCtrl',
activetab: 'machine'
}).
when('/jobs', {
templateUrl: 'html/jobs-overview.html',
controller: 'JobsOverviewCtrl',
activetab: 'jobs'
}).
when('/phones/:phoneId', {
templateUrl: 'html/phone-detail.html',
controller: 'PhoneDetailCtrl',
activetab: 'phone'
}).
otherwise({
redirectTo: '/machine'
});
}]);
答案 0 :(得分:16)
您的主要问题是您正在插入ng-disabled
而不是为其提供角度表达式。请参阅 documentation 中的参数定义。插值(使用 {{}}
)表达式使表达式仅在ng-disabled
指令中计算一次。
简单地改变:
<button ng-disabled="
{{
(component.price_next <= 0) || (component.price_next > user.values.euro) ||
(user.values.energy_remaining < (component.energy_next-component.energy))
}}"
ng-click="upgradeComponent(component)" class="btn btn-danger" role="button">
Upgrade {{component.text}} for <span class="glyphicon glyphicon-euro"></span>
{{component.price_next}}
</button>
到
<button ng-disabled="(component.price_next <= 0) || (component.price_next > user.values.euro) ||
(user.values.energy_remaining < (component.energy_next-component.energy))"
ng-click="upgradeComponent(component)" class="btn btn-danger" role="button">
Upgrade {{component.text}} for <span class="glyphicon glyphicon-euro"></span>
{{component.price_next}}
</button>
答案 1 :(得分:1)
你的情景: 当用户单击按钮时将其禁用,然后当您的操作完成后,您希望返回到启用的按钮。
我应该做的是创建一个指令,在按钮执行操作时管理按钮的状态,你正在做什么操作并不重要....!
baign说,你的问题的一个可能的答案可能是使用promises并在你的'click'事件中返回一个promise,这样你可以在用户点击它时将按钮设置为true,并在以后再次启用它你的承诺得到了解决。
看一下这个指令:
angular.module('app').directive('clickState', [
function() {
return {
priority:-1,
restrict: 'A',
scope: {
clickState: '&'
},
link: function postLink(scope, element, attrs) {
element.bind('click', function(){
element.prop('disabled', true);
scope.clickState().finally(function() {
element.prop('disabled', false);
});
});
}
};
}
]);
<强>用法:强>
<button click-state="updateMachine()" type="submit">submit</button>
<强>控制器:强>
var p = $q.defer()
$scope.updateMachine = function() {
$http.get('api/machine.php').success(function(data) {
$scope.machine = data;
p.resolve(); //it could be p.resolve(data); to pass the data with the promise
});
return p.promise()
}
答案 2 :(得分:1)
在阅读$ scope。$ apply和$ scope。$ watch时,我找到了解决方案:当我更改请求的顺序时,一切正常。因为在更新用户数据(如钱)时,没有为机器表触发更新。将代码更改为首先更新$ scope.user,然后在$ scope.machine之后解决此问题。我正在制作这个社区维基。