AngularJS中ng-disabled条件为false时未启用控件的问题求助
问题分析与解决方案
你遇到的核心问题有两个:指令模板重复声明控制器导致作用域隔离,以及**ng-disabled的判断逻辑错误**,这两个问题共同导致子模块复选框无法根据父模块的选中状态正常启用。
1. 移除指令模板中的重复控制器声明
你的指令已经通过scope: { array: '=', value: '=' }和父控制器建立了双向绑定,但模板里额外添加的ng-controller='aCtrl'会创建一个全新的控制器实例——这个实例和页面上的父控制器完全独立,所以模板里调用的deselect、读取的状态变量都是新实例里的,和你点击父模块修改的那个作用域完全不联动。
修改你的template.html,直接去掉ng-controller='aCtrl':
<table border="1"> <tr> <td>Check</td> <td>Submodule</td> </tr> <tr ng-repeat="submod in array" ng-if="submod.mod == value"> <td> <input type="checkbox" name="submodule" value="{{submod.name}}" ng-model="submod.selected" ng-click="deselect(submod.mod)" ng-disabled="!moduleStates[submod.mod]"> </td> <td>{{submod.name}}</td> </tr> </table>
2. 修正ng-disabled的判断逻辑 & 优化状态管理
原来的ng-disabled="submod.mod"是判断字符串是否为真(非空字符串永远返回true),所以复选框会一直处于禁用状态。我们需要判断的是父模块是否被选中,也就是父控制器中对应的WW、APS等变量是否为true。
这里更推荐把分散的状态变量统一放到一个对象里,既方便维护,也更容易和指令传递:
步骤1:修改父控制器的状态管理
把分散的$scope.WW、$scope.APS等变量整合到一个对象中,同时调整相关方法的逻辑:
app.controller('aCtrl', function($scope) { $scope.values = [{"name" : "1" , "mod" : "WW" , "selected" : false}, ...]; $scope.val = ""; // 用对象统一管理所有模块的选中状态 $scope.moduleStates = { WW: false, APS: false, // 补充其他模块的初始状态... }; function tester(param) { $scope.val = param; } function modifyValues(param , sel) { // 更新values数组中对应模块的selected状态 for (var i = 0; i < $scope.values.length; ++i) { if (param == $scope.values[i].mod) { $scope.values[i]["selected"] = sel; } } // 更新统一管理的模块状态 $scope.moduleStates[param] = sel; } function deselect(param) { // 取消模块选中状态 $scope.moduleStates[param] = false; // 同步更新values数组中的状态 modifyValues(param, false); } $scope.deselect = deselect; $scope.modifyValues = modifyValues; $scope.tester = tester; })
步骤2:更新指令的作用域绑定
把统一的状态对象传递给指令,确保指令能访问到父控制器的状态:
app.directive('myTable' , function() { return { restrict: 'E', scope: { array: '=', value: '=', deselect: '&', // 传递deselect方法 moduleStates: '=' // 传递统一的状态对象 }, templateUrl: 'template.html' } });
步骤3:更新页面上的指令调用
传递对应的方法和状态对象:
<my-table array="values" value="val" deselect="deselect(param)" module-states="moduleStates" ></my-table>
步骤4:修正模板中的ng-click和ng-disabled
现在模板里可以通过moduleStates[submod.mod]判断父模块是否选中,调整后的复选框代码:
<input type="checkbox" name="submodule" value="{{submod.name}}" ng-model="submod.selected" ng-click="deselect({param: submod.mod})" ng-disabled="!moduleStates[submod.mod]" >
3. 效果验证
现在操作流程会变成:
- 点击父模块时,
modifyValues会把对应moduleStates的属性设为true,指令中的子模块复选框会自动启用(因为ng-disabled="!moduleStates[submod.mod]"此时为false)。 - 点击子模块的复选框时,
deselect会把对应moduleStates的属性设为false,子模块复选框会再次禁用。
内容的提问来源于stack exchange,提问作者Sparker0i
相关产品推荐
相关产品推荐

