ng-disabled no evaluado después del cambio de datos

Estoy escribiendo una aplicación donde el usuario puede actualizar componentes pagando con dinero del juego. Después de presionar el button "actualizar", se envía una request ajax al server y se actualiza el componente. Después de eso estoy emitiendo otra request ajax para recuperar la página de nuevos componentes. Pero mientras se actualizan los datos, ng-disabled no se vuelve a verificar, por lo que el button de actualización sigue siendo seleccionable cuando no debería. Volver a cargar la página o la ruta corrige esto. Pero volver a cargar la página no es una buena experiencia para el usuario.

Estoy haciendo este proyecto para aprender Angularjs, así que si hay algo mal en mi configuration o cómo hago algo, ¡por favor díganme!

Intento include todo el código relevante; si falta algo, puede verlo en este enlace con el usuario y la contraseña "testing".

Para una cabecera, en machine-overview.html el button llama a upgradeComponent en el controller.js controller.js MachineOverviewCtrl emitiendo una request Ajax y al actualizar con éxito $scope.user y $scope.machine , los datos modificados se reflejan en la vista ( ng-repeat ) pero los botones ng-disabled no se evalúan y mantienen el estado anterior.

¿Qué estoy haciendo mal? ¿Cómo puedo forzar una evaluación o hacer la actualización de una manera que a Angularjs le gusta?

editar:

A la respuesta de @jack.the.ripper le falta el punto de que hay varios botones, uno por cada ng-repeat, pero esos botones solo no evalúan su directiva ng-disable.

imagen de ejemplo

//editar

index.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> 

machine-overview.html

 <!--ommited divs--> <table class="table table-bordenetworking"> <!--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--> 

javascript vars y su origen:

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

app.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({ networkingirectTo: '/machine' }); }]); 

controller.js

 var hacksControllers = angular.module('hacksControllers', ['hacksFilters']); hacksControllers.controller('hacksUserCtrl', ['$scope', '$http', '$interval', '$route', function ($scope, $http, $interval, $route) { $scope.$route = $route; $scope.updateUser = function() { $http.get('api/user.php').success(function(data) { $scope.user = data; if(!$scope.user.loggedIn){ window.location = "index.php"; } }); } $scope.updateUser(); $interval($scope.updateUser, 60000); }]); hacksControllers.controller('MachineOverviewCtrl', ['$scope', '$http', '$interval', function ($scope, $http, $interval) { $scope.machine = []; $scope.updateMachine = function() { $http.get('api/machine.php').success(function(data) { $scope.machine = data; }); } $scope.updateMachine(); $interval($scope.updateMachine, 60000); $scope.upgradeComponent = function(component){ var params = {name: component.name}; $http({ method: 'POST', url: 'api/machine-upgrade.php', data: $.param(params), headers: {'Content-Type': 'application/x-www-form-urlencoded'} }).success(function(data) { $scope.updateMachine(); $scope.updateUser(); }); } }]); 

3 Solutions collect form web for “ng-disabled no evaluado después del cambio de datos”

Tu principal problema es que estás interpolando ng-disabled lugar de proporcionarle una expresión angular. Ver la definición de arguments en la documentation . Interpolando (usando {{}} ) la expresión hace que la expresión se evalúe solo una vez dentro de la directiva ng-disabled .

Simplemente cambia:

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

a

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

su escenario: cuando un usuario hace clic en un button, lo desactiva, y cuando se completa su operación, desea volver al button para habilitarlo.

lo que debería hacer es crear una directiva que administre el estado del button mientras el button realiza la operación, ¡no importa qué operación está haciendo …!

Baign dijo que una posible respuesta a su problema podría ser utilizar promises y devolver una promise en sus events de "clic", de esa manera puede configurar el button para deshabilitar "true" cuando el usuario click él y lo habilite nuevamente cuando su promise llegue resuelto.

eche un vistazo a esta directiva:

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

uso:

 <button click-state="updateMachine()" type="submit">submit</button> 

controller:

 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() } 

Al leer $ scope. $ Apply y $ scope. $ Watch encontré la solución a esto: cuando cambio el order de mis requestes, todo funciona. Porque al actualizar los datos de usuario (como dinero) no hay una actualización activada para la tabla de la máquina. Cambiar el código para la primera actualización $ scope.user y después de eso $ scope.machine resuelve este problema. Estoy haciendo esta wiki de la comunidad.

  • Eliminar la opción "Todos los files" del cargador
  • ¿Cómo puedo desactivar el resaltado en html o JS?
  • Despachar evento de rueda del mouse en otro elemento DOM
  • ¿Puedo usar la label para una label?
  • Quiero retrasar un enlace por un período de 500 con javascript
  • ¿Hay finalmente una manera de hacer que la refactorización funcione en JavaScript, proyectos HTML en Eclipse Kepler?
  • Evite escribir en la input del campo de text, aunque el campo no esté desactivado / solo lectura
  • ¿Cómo atrapar el evento de clic derecho?
  • Javascript tiene muchos buenos JS marco (como Node.js AngularJS Vue.js React.js) es el mejor lenguaje de script.