ng-disabled在数据更改后未进行评估

时间:2014-09-11 22:09:13

标签: javascript html ajax angularjs

我正在编写一个应用程序,用户可以升级使用游戏币支付的组件。按下“升级”按钮后,会向服务器发送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指令。

example image

//修改

的index.html

ng-disabled

机器overview.html

<!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-->

app.js

$scope.user.x //hacksUserCtrl
$scope.machine.x //MachineOverviewCtrl

controller.js

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

3 个答案:

答案 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之后解决此问题。我正在制作这个社区维基。