阿里云新用户优惠

二十、UI-Grid Edit Feature 编辑功能

原文:201 Edit Feature

ui.grid.edit 功能允许对表格数据进行内嵌编辑。要启用, 必须引入 “ui.grid.edit” 模块, 必须在表格元素上引入ui-grid-edit编辑指令。

api 文档中提供了编辑功能的文档, 特别是:

  • columnDef
  • gridOptions
  • publicApi

可以使用列定义中的 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 编辑部件-日期选取器、下拉列表和输入框本身。如果你的浏览器没有实现这些小部件, 你就不会得到它们。如果您的浏览器以一种不理想的方式实现这些小部件 (例如, 某些浏览器不允许使用数字字段开始 “.”, 因此您不能键入 “.5”), 然后您需要提供一个自定义编辑器。在中期路线图中, 有意图提供bootstrap 功能, 这将提供与 angular-bootstrap 指令兼容的指令, 允许使用bootstrap datepicker 和输入字段。

$scope.gridOptions.columnDefs = [
   { name: 'name', enableCellEdit: true },
   { name: 'age', enableCellEdit: true, type: 'number'},
   { name: 'registered', displayName: 'Registered' , type: 'date'},
   { name: 'address', displayName: 'Address', type: 'object'},
   { name: 'address.city', enableCellEdit: true, displayName: 'Address (even rows editable)', cellEditableCondition: function($scope){return $scope.rowRenderIndex%2} }
   { name: 'isActive', enableCellEdit: true, type: 'boolean'},
]
  • index.html
<!doctype html>
<html ng-app="app">
  <head>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular-touch.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular-animate.js"></script>
    <script src="http://ui-grid.info/docs/grunt-scripts/csv.js"></script>
    <script src="http://ui-grid.info/docs/grunt-scripts/pdfmake.js"></script>
    <script src="http://ui-grid.info/docs/grunt-scripts/vfs_fonts.js"></script>
    <script src="http://ui-grid.info/release/ui-grid.js"></script>
    <script src="http://ui-grid.info/release/ui-grid.css"></script>
    <script src="app.js"></script>
  </head>
  <body>
    <div ng-controller="MainCtrl">
      <strong>Data Length:</strong> {{ gridOptions.data.length | number }}
      <br>
      <strong>Last Cell Edited:</strong> {{msg.lastCellEdited}}
      <br>
      <div ui-grid="gridOptions" ui-grid-edit class="grid"></div>
      <br>
      <div><strong>Last file uploaded:</strong></div>
      <div>{{lastFile}}</div>
    </div>
  </body>
</html>
  • main.css
.grid {
  width: 600px;
  height: 450px;
}
  • app.js
var app = angular.module('app', ['ngTouch', 'ui.grid', 'ui.grid.edit', 'addressFormatter']);

angular.module('addressFormatter', []).filter('address', function () {
  return function (input) {
      return input.street + ', ' + input.city + ', ' + input.state + ', ' + input.zip;
  };
});

app.controller('MainCtrl', ['$scope', '$http', '$timeout', function ($scope, $http, $timeout) {
  $scope.gridOptions = {  };

  $scope.storeFile = function( gridRow, gridCol, files ) {
    // ignore all but the first file, it can only select one anyway
    // set the filename into this column
    gridRow.entity.filename = files[0].name;

    // read the file and set it into a hidden column, which we may do stuff with later
    var setFile = function(fileContent){
      gridRow.entity.file = fileContent.currentTarget.result;
      // put it on scope so we can display it - you'd probably do something else with it
      $scope.lastFile = fileContent.currentTarget.result;
      $scope.$apply();
    };
    var reader = new FileReader();
    reader.onload = setFile;
    reader.readAsText( files[0] );
  };

  $scope.gridOptions.columnDefs = [
    { name: 'id', enableCellEdit: false, width: '10%' },
    { name: 'name', displayName: 'Name (editable)', width: '20%' },
    { name: 'age', displayName: 'Age' , type: 'number', width: '10%' },
    { name: 'gender', displayName: 'Gender', editableCellTemplate: 'ui-grid/dropdownEditor', width: '20%',
      cellFilter: 'mapGender', editDropdownValueLabel: 'gender', editDropdownOptionsArray: [
      { id: 1, gender: 'male' },
      { id: 2, gender: 'female' }
    ] },
    { name: 'registered', displayName: 'Registered' , type: 'date', cellFilter: 'date:"yyyy-MM-dd"', width: '20%' },
    { name: 'address', displayName: 'Address', type: 'object', cellFilter: 'address', width: '30%' },
    { name: 'address.city', displayName: 'Address (even rows editable)', width: '20%',
         cellEditableCondition: function($scope){
         return $scope.rowRenderIndex%2
         }
    },
    { name: 'isActive', displayName: 'Active', type: 'boolean', width: '10%' },
    { name: 'pet', displayName: 'Pet', width: '20%', editableCellTemplate: 'ui-grid/dropdownEditor',
      editDropdownRowEntityOptionsArrayPath: 'foo.bar[0].options', editDropdownIdLabel: 'value'
    },
    { name: 'status', displayName: 'Status', width: '20%', editableCellTemplate: 'ui-grid/dropdownEditor',
      cellFilter: 'mapStatus',
      editDropdownOptionsFunction: function(rowEntity, colDef) {
        var single;
        var married = {id: 3, value: 'Married'};
        if (rowEntity.gender === 1) {
          single = {id: 1, value: 'Bachelor'};
          return [single, married];
        } else {
          single = {id: 2, value: 'Nubile'};
          return $timeout(function() {
            return [single, married];
          }, 100);
        }
      }
    },
    { name: 'filename', displayName: 'File', width: '20%', editableCellTemplate: 'ui-grid/fileChooserEditor',
      editFileChooserCallback: $scope.storeFile }
  ];

 $scope.msg = {};

 $scope.gridOptions.onRegisterApi = function(gridApi){
          //set gridApi on scope
          $scope.gridApi = gridApi;
          gridApi.edit.on.afterCellEdit($scope,function(rowEntity, colDef, newValue, oldValue){
            $scope.msg.lastCellEdited = 'edited row id:' + rowEntity.id + ' Column:' + colDef.name + ' newValue:' + newValue + ' oldValue:' + oldValue ;
            $scope.$apply();
          });
        };

  $http.get('http://ui-grid.info/data/500_complex.json')
    .success(function(data) {
      for(i = 0; i < data.length; i++){
        data[i].registered = new Date(data[i].registered);
        data[i].gender = data[i].gender==='male' ? 1 : 2;
        if (i % 2) {
          data[i].pet = 'fish'
          data[i].foo = {bar: [{baz: 2, options: [{value: 'fish'}, {value: 'hamster'}]}]}
        }
        else {
          data[i].pet = 'dog'
          data[i].foo = {bar: [{baz: 2, options: [{value: 'dog'}, {value: 'cat'}]}]}
        }
      }
      $scope.gridOptions.data = data;
    });
}])

.filter('mapGender', function() {
  var genderHash = {
    1: 'male',
    2: 'female'
  };

  return function(input) {
    if (!input){
      return '';
    } else {
      return genderHash[input];
    }
  };
})

.filter('mapStatus', function() {
  var genderHash = {
    1: 'Bachelor',
    2: 'Nubile',
    3: 'Married'
  };

  return function(input) {
    if (!input){
      return '';
    } else {
      return genderHash[input];
    }
  };
});

关注微信公众号,与我交流吧~

分享