该表是通过在行模板上进行ng重复创建的.我需要做一些所有涉及到访问由ng-repeat创建的范围的事情.我需要
>检测行是否可编辑,何时不可编辑
>当第一个下拉列表更改时,过滤第二个丢弃列表的选项
为了尝试使用此演示,我已经为单独的行添加了一个控制器.这给了我一些访问窗体(name = rowform),但是我仍然无法在“make”属性上设置一个手表.当用户进行选择时,我甚至不能发现表单的属性正在改变.
如何在“make”属性上设置手表?
页面控制器
angular.module('app').controller("quoteBuckingRaterController",function ($scope,$q,$filter,listService,transactionDataService) { $scope.equipment = []; $scope.makes = []; $scope.models = []; $scope.showModel = function(equip) { if(equip.model) { var selected = $filter('filter')($scope.models,{id: equip.model}); return selected.length ? selected[0].name : 'Not set'; } else { return 'Not set'; } }; $scope.showMake = function(equip) { if (equip.model) { var selected = $filter('filter')($scope.models,{ id: equip.model }); if (selected.length && selected.length > 0) { if (equip.make != selected[0].make) equip.make = selected[0].make; return selected[0].make; } else { return 'Not set'; } } else { return 'Not set'; } }; $scope.checkName = function (data,id) { if (!data) { return "Description is required"; } }; $scope.checkModel = function (data,id) { if (!data) { return "Model is required"; } }; $scope.saveEquipment = function (data,id) { $scope.inserted = null; }; $scope.cancelRowEdit = function (data,id) { $scope.inserted = null; }; $scope.removeEquipment = function(index) { $scope.equipment.splice(index,1); }; $scope.addEquipment = function() { $scope.inserted = { id: $scope.equipment.length+1,name: '',make: null,model: null }; $scope.equipment.push($scope.inserted); }; $scope.filterModels = function (make) { $scope.models = _.where($scope.allModels,function(item) { return item.make == make; }); }; //called by another process when page loads $scope.initialize = function (loaded) { return $q(function (resolve,reject) { if (!loaded) { listService.getEquipmentModels().then(function (data) { $scope.allModels = data; $scope.models = data; //uses underscore.js $scope.makes = _.chain(data) .map(function (item) { var m = { id: item.make,name: item.make }; return m; }) .uniq() .value(); resolve(); }); } }); } });
行控制器
angular.module('app').controller("editRowController",function ($scope) { $scope.testClick = function () { alert('button clicked'); }; $scope.make = null; $scope.$watch('make',function () { alert('how do I tell when the make has been changed?'); this.$parent.$parent.filterModels(make.id); }); });
HTML
<div> <div class="col-md-12" style="margin-bottom: 3px"> <div class="col-md-4 col-md-offset-1" style="padding-top: 6px; padding-left: 0px"><label>Equipment</label></div> <div class="col-md-offset-10"> <button class="btn btn-primary btn-sm" ng-click="addEquipment()">Add row</button> </div> </div> <div class="col-md-10 col-md-offset-1"> <table class="table table-bordered table-hover table-condensed"> <tr style="font-weight: bold; background-color: lightblue"> <td style="width:35%">Name</td> <td style="width:20%">Make</td> <td style="width:20%">Model</td> <td style="width:25%">Edit</td> </tr> <tr ng-repeat="equip in equipment" ng-controller="editRowController"> <td> <!-- editable equip name (text with validation) --> <span editable-text="equip.name" e-name="name" e-form="rowform" onbeforesave="checkName($data,equip.id)" e-required> {{ equip.name || 'empty' }} </span> </td> <td> <!-- editable make (select-local) --> <span editable-select="equip.make" e-name="make" e-form="rowform" e-ng-options="s.value as s.name for s in makes"> {{ showMake(equip) }} </span> </td> <td> <!-- editable model (select-remote) --> <span editable-select="equip.model" e-name="model" e-form="rowform" e-ng-options="g.id as g.name for g in models" onbeforesave="checkModel($data,equip.id)" e-required> {{ showModel(equip) }} </span> <button type="button" ng-disabled="rowform.$waiting" ng-click="testClick()" class="btn btn-default"> test </button> </td> <td style="white-space: nowrap"> <!-- form --> <form editable-form name="rowform" onbeforesave="saveEquipment($data,equip.id)" ng-show="rowform.$visible" class="form-buttons form-inline" shown="inserted == equip"> <button type="submit" ng-disabled="rowform.$waiting" class="btn btn-primary"> save </button> <button type="button" ng-disabled="rowform.$waiting" ng-click="rowform.$cancel()" class="btn btn-default"> cancel </button> </form> <div class="buttons" ng-show="!rowform.$visible"> <button class="btn btn-primary" ng-click="rowform.$show()">edit</button> <button class="btn btn-danger" ng-click="removeEquipment($index)">del</button> </div> </td> </tr> </table> </div> </div>
解决方法
ng-repeat
creates a child scope for each row(每台设备).因此,EditRowController的范围是父引用BuckingRaterController的childScope.
此childScope包含:
>父范围的所有属性(例如,设备,制造,型号)
>该属性装备了由ng-repeat提供的设备阵列的一个值
>在ng-repeat块内定义的任何附加范围属性,例如. rowform
因此,您可以使用$scope变量访问childController editRowController中的这些属性,例如:
$scope.equip.make $scope.equipment
并在html文件中的ng-repeat元素内使用angular expression,例如:
{{equip.make}} {{equipment}}
现在到$scope.$watch
:如果你提供一个字符串作为第一个参数,这是一个角度的表达式,像html文件,只是没有括号{{}}.装备示例:
$scope.$watch('equip.make',function (value) { console.log('equip.make value (on save): ' + value); });
但是,只有当用户保存该行时,angular-xeditable才会更新equip.make的值.如果要观看用户输入实时,则必须使用由angle-xeditable提供的rowform对象中的$data属性:
$scope.$watch('rowform.$data.make',function (value) { console.log('equip.make value (live): ' + value); },true);
您也可以使用ng-change:
<span editable-select="equip.make" e-name="make" e-ng-change="onMakeValueChange($data)" e-form="rowform" e-ng-options="s.value as s.name for s in makes">
JS:
$scope.onMakeValueChange = function(newValue) { console.log('equip.make value onChange: ' + newValue); }
您的第二个问题是如何检测行是否可编辑,何时不能,可以通过使用表单上的onshow / onhide属性或者将范围内的rowform对象的$visible属性视为documented in the angular-xeditable reference
<form editable-form name="rowform" onshow="setEditable(true)" onhide="setEditable(false)"> $scope.setEditable = function(value) { console.log('is editable? ' + value); }; // or $scope.$watch('rowform.$visible',function(value) { console.log('is editable? ' + value); });
您可能会问为什么rowform对象在当前的childScope中.
它由< form>创建标签. See the Angular Reference about the built-in form directive:
Directive that instantiates FormController.
If the name attribute is specified,the form controller is published
onto the current scope under this name.
一个包含示例代码的工作片段:
angular.module('app',["xeditable"]); angular.module('app').controller("editRowController",function ($scope) { $scope.testClick = function () { alert('button clicked'); }; $scope.$watch('equip.make',function (value) { console.log('equip.make value (after save): ' + value); }); $scope.$watch('rowform.$data.make',function (value) { console.log('equip.make value (live): ' + value); },true); // detect if row is editable by using onshow / onhide on form element $scope.setEditable = function(value) { console.log('is equip id ' + $scope.equip.id + ' editable? [using onshow / onhide] ' + value); }; // detect if row is editable by using a watcher on the form property $visible $scope.$watch('rowform.$visible',function(value) { console.log('is equip id ' + $scope.equip.id + ' editable [by watching form property]? ' + value); }); }); angular.module('app').controller("quoteBuckingRaterController",$filter) { $scope.equipment = []; $scope.makes = [{value: 1,name: 'Horst'},{value: 2,name: 'Fritz'}]; $scope.models = [{id: 1,name: 'PC',make: 1}]; $scope.showModel = function(equip) { if(equip.model) { var selected = $filter('filter')($scope.models,{id: equip.model}); return selected.length ? selected[0].name : 'Not set'; } else { return 'Not set'; } }; $scope.showMake = function(equip) { if (equip.model) { var selected = $filter('filter')($scope.models,{ id: equip.model }); if (selected.length && selected.length > 0) { if (equip.make != selected[0].make) equip.make = selected[0].make; return selected[0].make; } else { return 'Not set'; } } else { return 'Not set'; } }; $scope.checkName = function (data,id) { if (!data) { return "Description is required"; } }; $scope.checkModel = function (data,id) { if (!data) { return "Model is required"; } }; $scope.saveEquipment = function (data,id) { $scope.inserted = null; }; $scope.cancelRowEdit = function (data,id) { $scope.inserted = null; }; $scope.removeEquipment = function(index) { $scope.equipment.splice(index,1); }; $scope.addEquipment = function() { $scope.inserted = { id: $scope.equipment.length+1,model: null }; $scope.equipment.push($scope.inserted); }; });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-xeditable/0.1.9/js/xeditable.js"></script> <link href="https://cdnjs.cloudflare.com/ajax/libs/angular-xeditable/0.1.9/css/xeditable.css" rel="stylesheet"/> <link href="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet"/> <div ng-app="app" ng-controller="quoteBuckingRaterController"> <div class="col-md-12" style="margin-bottom: 3px"> <div class="col-md-4 col-md-offset-1" style="padding-top: 6px; padding-left: 0px"><label>Equipment</label></div> <div class="col-md-offset-10"> <button class="btn btn-primary btn-sm" ng-click="addEquipment()">Add row</button> </div> </div> <div class="col-md-10 col-md-offset-1"> <table class="table table-bordered table-hover table-condensed"> <tr style="font-weight: bold; background-color: lightblue"> <td style="width:35%">Name</td> <td style="width:20%">Make</td> <td style="width:20%">Model</td> <td style="width:25%">Edit</td> </tr> <tr ng-repeat="equip in equipment" ng-controller="editRowController"> <td> <!-- editable equip name (text with validation) --> <span editable-text="equip.name" e-name="name" e-form="rowform" onbeforesave="checkName($data,equip.id)" ng-show="rowform.$visible" class="form-buttons form-inline" shown="inserted == equip" onshow="setEditable(true)" onhide="setEditable(false)"> <button type="submit" ng-disabled="rowform.$waiting" class="btn btn-primary"> save </button> <button type="button" ng-disabled="rowform.$waiting" ng-click="rowform.$cancel()" class="btn btn-default"> cancel </button> </form> <div class="buttons" ng-show="!rowform.$visible"> <button class="btn btn-primary" ng-click="rowform.$show()">edit</button> <button class="btn btn-danger" ng-click="removeEquipment($index)">del</button> </div> </td> </tr> </table> </div> </div>