(转)UI-Grid 编辑功能
ui.grid.edit 功能允许对表格数据进行内嵌编辑。要启用, 必须包括 “ui.grid.edit” 模块, 必须在表格元素上包括ui-grid-edit编辑指令。
api 文档中提供了编辑功能的文档, 特别是:
可以使用列定义中的 enableCellEdit 选项来允许列可编辑。
通过双击、f2、或开始键入任何 non-navigable 键来调用编辑。可以通过tab, enter 或 esc 结束单元格的编辑, 并且tab, 左或右箭头, enter或 esc 为也可以应用在下拉中。
默认情况下, 为所有字段提供了输入元素, 其中有数字、日期和复选框编辑器, 用于为指定了 “数字”、”日期” 和 “布尔” 类型的字段提供一个简单的文本编辑器。(关于日期编辑器的一点值得注意的是, 对于要启用的日期编辑器, 变量的数据类型也应该是 “日期”)
通过 columnDef 上设置 editableCellTemplate : ui-grid/dropdownEditor, 还可以使用下拉编辑器。当使用下拉编辑器时, 您需要通过 columnDef 的 editDropDownOptionsArray 属性提供一个选项数组。默认情况下, 此数组应为 {id: xxx, value: xxx}, 还可以通过使用 editDropdownIdLabel 和 editDropdownValueLabel 选项来更改字段标记。
通过columnDef 上设置 editableCellTemplate : ui-grid/fileChooserEditor, 可以使用文件选择器。此文件选择器将打开用户选择的文件, 并向模型元素分配该文件的值。在下面的示例中, 我们使用文件选择器加载一个文件, 我们在单元格中显示文件名。文件存储在隐藏列中的行, 我们可以保存到服务器或其他进程。
自定义编辑模板应用于除默认编辑器以外的任何编辑, 但请注意, 您可能还需要提供类似于 uiGridEditor 指令的自定义指令, 以便提供 BEGIN_CELL_EDIT、CANCEL_CELL_EDIT 和 END_CELL_EDIT 事件。
ColumnDef Options:
- editModelField (default: undefined) -要使用的可绑定表达式, 而不是 colDef.field 绑定编辑控件时的字段。
- editableCellTemplate (default: ‘ui-grid/cellEditor’) - 在调用编辑模式时返回要编译的 html 内容中有效的html、templateCache id 或 url。
- enableCellEdit (default: 默认所有列都为true) -true 将启用编辑和 false 将禁用它。
- cellEditableCondition (default: true)- 可以设置为一个布尔值或函数, 它将用cellScope 观察器来调用, 以确定是否应在编辑模式下调用该单元格。
- type (default: ‘string’)-如果设置为 “数字”、”布尔” 或 “日期”, 则为编辑提供的默认编辑器将分别为数字或布尔值或日期编辑器。如果设置为 “对象”, 则默认情况下该列将不可编辑。请注意, 此类型列也用于 ui-grid中的其他用途, 包括排序逻辑。
- editDropdownOptionsArray-如果下拉列表, 需要用一个值数组填充, 默认情况下, 这些值应该为 {id: xxx, value: xxx}, 标签可以用下面两个选项进行调整。
- editDropdownIdLabel (default: ‘id’) - 控制选项数组中的 id 标签, 因此, 如果数组恰好包含 “代码”, 则可以使用它而不必重新处理数组。
- editDropdownValueLabel (default: ‘value’) - 控制选项数组中的值标签-如果数组恰好包含 “name”, 则可以使用它而不必重新处理数组。
- editDropdownRowEntityOptionsArrayPath - 当下拉列表的内容依赖于该行支持的实体时, 可以作为 editDropdownOptionsArray 的替代方法。
- editDropdownOptionsFunction - 当可以使用参数为行实体和列定义的函数检索内容时, 可以作为 editDropdownOptionsArray 的另一种替代方法。
- editDropdownFilter (default: ”) - 允许您将筛选器应用于 “编辑” 下拉选项中的值, 例如, 如果您使用的是角平移, 则将此设置为 “平移”
只有在使用 cellNav 功能时, 以下选项才可用
- enableCellEditOnFocus - true 当单元格具有焦点时调用编辑器
请注意, 编辑功能使用本机 html5 编辑部件-日期选取器、下拉列表和输入框本身。如果你的浏览器没有实现这些小部件, 你就不会得到它们。如果您的浏览器以一种不理想的方式实现这些小部件 (例如, 某些浏览器不允许使用数字字段开始 “.”, 因此您不能键入 “. 五”), 然后您需要提供一个自定义编辑器。在中期路线图中, 有意图提供bootstrap 功能, 这将提供与 angular-bootstrap 指令兼容的指令, 允许使用bootstrap datepicker 和输入字段。
1 $scope.gridOptions.columnDefs = [ 2 { name: 'name', enableCellEdit: true }, 3 { name: 'age', enableCellEdit: true, type: 'number'}, 4 { name: 'registered', displayName: 'Registered' , type: 'date'}, 5 { name: 'address', displayName: 'Address', type: 'object'}, 6 { name: 'address.city', enableCellEdit: true, displayName: 'Address (even rows editable)', cellEditableCondition: function($scope){return $scope.rowRenderIndex%2} } 7 { name: 'isActive', enableCellEdit: true, type: 'boolean'}, 8 ]
代码
index.html
1 <!doctype html> 2 <html ng-app="app"> 3 <head> 4 <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.js"></script> 5 <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular-touch.js"></script> 6 <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular-animate.js"></script> 7 <script src="http://ui-grid.info/docs/grunt-scripts/csv.js"></script> 8 <script src="http://ui-grid.info/docs/grunt-scripts/pdfmake.js"></script> 9 <script src="http://ui-grid.info/docs/grunt-scripts/vfs_fonts.js"></script> 10 <script src="/release/ui-grid.js"></script> 11 <script src="/release/ui-grid.css"></script> 12 <script src="app.js"></script> 13 </head> 14 <body> 15 <div ng-controller="MainCtrl"> 16 <strong>Data Length:</strong> {{ gridOptions.data.length | number }} 17 <br> 18 <strong>Last Cell Edited:</strong> {{msg.lastCellEdited}} 19 <br> 20 <div ui-grid="gridOptions" ui-grid-edit class="grid"></div> 21 <br> 22 <div><strong>Last file uploaded:</strong></div> 23 <div>{{lastFile}}</div> 24 </div> 25 </body> 26 </html>
main.css
1 .grid { 2 width: 600px; 3 height: 450px; 4 }
app.js
1 var app = angular.module('app', ['ngTouch', 'ui.grid', 'ui.grid.edit', 'addressFormatter']); 2 3 angular.module('addressFormatter', []).filter('address', function () { 4 return function (input) { 5 return input.street + ', ' + input.city + ', ' + input.state + ', ' + input.zip; 6 }; 7 }); 8 9 app.controller('MainCtrl', ['$scope', '$http', '$timeout', function ($scope, $http, $timeout) { 10 $scope.gridOptions = { }; 11 12 $scope.storeFile = function( gridRow, gridCol, files ) { 13 // ignore all but the first file, it can only select one anyway 14 // set the filename into this column 15 gridRow.entity.filename = files[0].name; 16 17 // read the file and set it into a hidden column, which we may do stuff with later 18 var setFile = function(fileContent){ 19 gridRow.entity.file = fileContent.currentTarget.result; 20 // put it on scope so we can display it - you'd probably do something else with it 21 $scope.lastFile = fileContent.currentTarget.result; 22 $scope.$apply(); 23 }; 24 var reader = new FileReader(); 25 reader.onload = setFile; 26 reader.readAsText( files[0] ); 27 }; 28 29 $scope.gridOptions.columnDefs = [ 30 { name: 'id', enableCellEdit: false, width: '10%' }, 31 { name: 'name', displayName: 'Name (editable)', width: '20%' }, 32 { name: 'age', displayName: 'Age' , type: 'number', width: '10%' }, 33 { name: 'gender', displayName: 'Gender', editableCellTemplate: 'ui-grid/dropdownEditor', width: '20%', 34 cellFilter: 'mapGender', editDropdownValueLabel: 'gender', editDropdownOptionsArray: [ 35 { id: 1, gender: 'male' }, 36 { id: 2, gender: 'female' } 37 ] }, 38 { name: 'registered', displayName: 'Registered' , type: 'date', cellFilter: 'date:"yyyy-MM-dd"', width: '20%' }, 39 { name: 'address', displayName: 'Address', type: 'object', cellFilter: 'address', width: '30%' }, 40 { name: 'address.city', displayName: 'Address (even rows editable)', width: '20%', 41 cellEditableCondition: function($scope){ 42 return $scope.rowRenderIndex%2 43 } 44 }, 45 { name: 'isActive', displayName: 'Active', type: 'boolean', width: '10%' }, 46 { name: 'pet', displayName: 'Pet', width: '20%', editableCellTemplate: 'ui-grid/dropdownEditor', 47 editDropdownRowEntityOptionsArrayPath: 'foo.bar[0].options', editDropdownIdLabel: 'value' 48 }, 49 { name: 'status', displayName: 'Status', width: '20%', editableCellTemplate: 'ui-grid/dropdownEditor', 50 cellFilter: 'mapStatus', 51 editDropdownOptionsFunction: function(rowEntity, colDef) { 52 var single; 53 var married = {id: 3, value: 'Married'}; 54 if (rowEntity.gender === 1) { 55 single = {id: 1, value: 'Bachelor'}; 56 return [single, married]; 57 } else { 58 single = {id: 2, value: 'Nubile'}; 59 return $timeout(function() { 60 return [single, married]; 61 }, 100); 62 } 63 } 64 }, 65 { name: 'filename', displayName: 'File', width: '20%', editableCellTemplate: 'ui-grid/fileChooserEditor', 66 editFileChooserCallback: $scope.storeFile } 67 ]; 68 69 $scope.msg = {}; 70 71 $scope.gridOptions.onRegisterApi = function(gridApi){ 72 //set gridApi on scope 73 $scope.gridApi = gridApi; 74 gridApi.edit.on.afterCellEdit($scope,function(rowEntity, colDef, newValue, oldValue){ 75 $scope.msg.lastCellEdited = 'edited row id:' + rowEntity.id + ' Column:' + colDef.name + ' newValue:' + newValue + ' oldValue:' + oldValue ; 76 $scope.$apply(); 77 }); 78 }; 79 80 $http.get('/data/500_complex.json') 81 .success(function(data) { 82 for(i = 0; i < data.length; i++){ 83 data[i].registered = new Date(data[i].registered); 84 data[i].gender = data[i].gender==='male' ? 1 : 2; 85 if (i % 2) { 86 data[i].pet = 'fish' 87 data[i].foo = {bar: [{baz: 2, options: [{value: 'fish'}, {value: 'hamster'}]}]} 88 } 89 else { 90 data[i].pet = 'dog' 91 data[i].foo = {bar: [{baz: 2, options: [{value: 'dog'}, {value: 'cat'}]}]} 92 } 93 } 94 $scope.gridOptions.data = data; 95 }); 96 }]) 97 98 .filter('mapGender', function() { 99 var genderHash = { 100 1: 'male', 101 2: 'female' 102 }; 103 104 return function(input) { 105 if (!input){ 106 return ''; 107 } else { 108 return genderHash[input]; 109 } 110 }; 111 }) 112 113 .filter('mapStatus', function() { 114 var genderHash = { 115 1: 'Bachelor', 116 2: 'Nubile', 117 3: 'Married' 118 }; 119 120 return function(input) { 121 if (!input){ 122 return ''; 123 } else { 124 return genderHash[input]; 125 } 126 }; 127 }) 128 ;
Demo