原文:202 Cell Navigation

此示例使用 ui-grid-cellNav指令添加单元格导航。要启用, 必须包括 “ui.grid.cellNav” 模块, 并且必须在表格元素上包括ui-grid-cellNav指令。

CellNav 功能的文档在 api 文档中提供, 特别是:

columnDef
gridOptions
publicApi
CellNav 允许您使用箭头键、pg-down 和 pg-up 在网格周围导航、输入 (下移)、shift 输入 (向上移动)、tab (向右移动) 和 shift 键 (向左移动)。当与可编辑功能组合在一起时, 左向右箭头键将被并入 “深层编辑” 模式, 允许您在编辑的文本中移动。tab 键和 shift 键选项卡按键仍起作用。

使用 gridOptions. onRegisterApi 回调以在导航单元格时注册 on_cellNav 事件和日志。

提供一个示例, 请求滚动到特定的行或列以编程方式-对于记住页的状态并在用户返回时滚动回该位置非常有用。

提供一个滚动到特定单元格并使用 scrollToFocus api 设置焦点的示例。

提供了一个利用 modifierKeysToMultiSelectCells 选项和 getCurrentSelection api 函数来提取选定单元格的值的示例。

提供了一个示例, 说明使用 keyDownOverrides 添加自定义的 ctrl + Right 焦点到一行的最后一列, 同时仍然允许由表格处理右箭头。

代码:
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">
      <button type="button" class="btn btn-success" ng-click="scrollTo(20,0)">Scroll To Row 20</button>
      <button type="button" class="btn btn-success" ng-click="scrollTo(0,7)">Scroll To Balance</button>
      <button type="button" class="btn btn-success" ng-click="scrollTo(50,7)">Scroll To Row 50, Balance</button>
      <button type="button" class="btn btn-success" ng-click="scrollToFocus(50,7)">Focus Row 50, Balance</button>
      <button type="button" class="btn btn-success" ng-click="getCurrentFocus()">Get Current focused cell</button>  <span ng-bind="currentFocused"></span>
      <button type="button" class="btn btn-success" ng-click="getCurrentSelection()">Get Current focused cell values</button>
      <input type="text" ng-model="printSelection" placeholder="Click the 'Get current focused cell values' button to print cell values of selection here" class="printSelection">
      <br>
      <br>
      <div ui-grid="gridOptions" ui-grid-cellNav ui-grid-pinning class="grid"></div>
    </div>
  </body>
</html>

main.css

.grid {
  width: 500px;
  height: 400px;
}
.printSelection {
    width: 600px;
    margin-top: 10px;
}

app.js

var app = angular.module('app', ['ngTouch', 'ui.grid', 'ui.grid.cellNav', 'ui.grid.pinning']);

app.controller('MainCtrl', ['$scope', '$http', '$log', function ($scope, $http, $log) {
  $scope.gridOptions = {
    modifierKeysToMultiSelectCells: true,
    keyDownOverrides: [ { keyCode: 39, ctrlKey: true }],
    showGridFooter: true
  };
  $scope.gridOptions.columnDefs = [
    { name: 'id', width:'150' },
    { name: 'name', width:'200' },
    { name: 'age', displayName: 'Age (not focusable)', allowCellFocus : false, width:'100' },
    { name: 'address.city', width:'200' },
    { name: 'phone', width:'150' },
    { name: 'company', width:'150' },
    { name: 'email', width:'150' },
    { name: 'balance', width:'100' },
    { name: 'guid', width:'100' }
  ];

  $http.get('http://ui-grid.info/data/500_complex.json')
    .success(function(data) {
      $scope.gridOptions.data = data;
    });

    $scope.info = {};

    $scope.currentFocused = "";

    $scope.getCurrentFocus = function(){
      var rowCol = $scope.gridApi.cellNav.getFocusedCell();
      if(rowCol !== null) {
          $scope.currentFocused = 'Row Id:' + rowCol.row.entity.id + ' col:' + rowCol.col.colDef.name;
      }
    };

    $scope.getCurrentSelection = function() {
      var values = [];
      var currentSelection = $scope.gridApi.cellNav.getCurrentSelection();
      for (var i = 0; i < currentSelection.length; i++) {
        values.push(currentSelection[i].row.entity[currentSelection[i].col.name])
      }
      $scope.printSelection = values.toString();
    };

    $scope.scrollTo = function( rowIndex, colIndex ) {
      $scope.gridApi.core.scrollTo( $scope.gridOptions.data[rowIndex], $scope.gridOptions.columnDefs[colIndex]);
    };

    $scope.scrollToFocus = function( rowIndex, colIndex ) {
      $scope.gridApi.cellNav.scrollToFocus( $scope.gridOptions.data[rowIndex], $scope.gridOptions.columnDefs[colIndex]);
    };

    $scope.gridOptions.onRegisterApi = function(gridApi){
       $scope.gridApi = gridApi;
       gridApi.cellNav.on.navigate($scope,function(newRowCol, oldRowCol){
             // var rowCol = {row: newRowCol.row.index, col:newRowCol.col.colDef.name};
             // var msg = 'New RowCol is ' + angular.toJson(rowCol);
             // if(oldRowCol){
             //    rowCol = {row: oldRowCol.row.index, col:oldRowCol.col.colDef.name};
             //    msg += ' Old RowCol is ' + angular.toJson(rowCol);
             // }
              $log.log('navigation event');
            });
        gridApi.cellNav.on.viewPortKeyDown($scope,function(event, newRowCol){
                var row = newRowCol.row;
                var col = newRowCol.col
                if (event.keyCode === 39) {
                    $scope.gridApi.cellNav.scrollToFocus(row.entity, $scope.gridApi.grid.columns[$scope.gridApi.grid.columns.length - 1]);
                }
            });
    };
}]);

Demo

作者水平有限,不当之处敬请指正。
感谢您的阅读,如果觉得文章对您有帮助,请支持一下。

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

Demo

作者水平有限,不当之处敬请指正。
感谢您的阅读,如果觉得文章对您有帮助,请支持一下。

原文:191 Horizontal Scrolling

显示大量列的滚动

代码:
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>{{ gridOptions.columnDefs.length | number }} Columns with Random Widths</strong>
      <br>
      <br>
      <div id="grid1" ui-grid="gridOptions" class="grid" ng-if="gridOptions"></div>
    </div>
  </body>
</html>

main.css

.grid {
  width: 500px;
  height: 400px;
}

app.js

var app = angular.module('app', ['ngTouch', 'ui.grid']);

app.controller('MainCtrl', ['$scope', function ($scope) {
  var colCount = 500;
  var rowCount = 500;
  var gridOptions = {};

  function generateColumns() {
    for (var colIndex = 0; colIndex < colCount; colIndex++) {
      gridOptions.columnDefs.push({
        name: 'col' + colIndex,
        width: Math.floor(Math.random() * (120 - 50 + 1)) + 50
      });
    }
  }

  function generateData() {
    for (var rowIndex = 0; rowIndex < rowCount; rowIndex++) {
      var row = {};

      for (var colIndex = 0; colIndex < colCount; colIndex++) {
        row['col' + colIndex] = 'r' + rowIndex + 'c' + colIndex;
      }

      gridOptions.data.push(row);
    }
  }

  function initialize() {
    gridOptions = {
      enableSorting: true,
      fastWatch: true,
      columnDefs: [],
      data: []
    };
    generateColumns();
    generateData();

    $scope.gridOptions = gridOptions;
  }

  initialize();
}]);

Demo

作者水平有限,不当之处敬请指正。
感谢您的阅读,如果觉得文章对您有帮助,请支持一下。

原文:190 Large Dataset

这个表格示例使用10000个记录的数据集。

演示如下:
– 绑定复杂的列属性 城市.地址。
– 同一字段可以在具有不同名称的表格中列出两次
– 使用字段而不是名称便于2.x 向后兼容

代码:
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>
      <br>
      <div id="grid1" ui-grid="gridOptions" class="grid"></div>
    </div>
  </body>
</html>

main.css

.grid {
  width: 500px;
  height: 450px;
}

app.js

var app = angular.module('app', ['ngTouch', 'ui.grid']);

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

  $scope.gridOptions.columnDefs = [
    {name:'id'},
    {name:'name'},
    {field:'age'}, // showing backwards compatibility with 2.x.  you can use field in place of name
    {name: 'address.city'},
    {name: 'age again', field:'age'}
  ];

  var canceler = $q.defer();
  $http.get('http://ui-grid.info/data/10000_complex.json', {timeout: canceler.promise})
    .success(function(data) {
      $scope.gridOptions.data = data;
    });

  $scope.$on('$destroy', function(){
    canceler.resolve();  // Aborts the $http request if it isn't finished.
  });
}]);

Demo

作者水平有限,不当之处敬请指正。
感谢您的阅读,如果觉得文章对您有帮助,请支持一下。

原文:122 Accessibility

无障碍性 (或 A11Y) 通常是 web 开发中被忽略的方面。确保您的内容是可访问的, 类似于确保您的内容在所有主要浏览器上都可见。如果您在设计网站时不考虑辅助功能, 则您的内容将无法供所有用户使用。

先决条件:

  • 引入 angular-aria (Angular 1.3.0+)。
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-aria.js"></script>
<link rel="styleSheet" href="release/ui-grid-unstable.css"/>
<script src="/release/ui-grid-unstable.js"></script>
  • 在app中依赖注入 ngAria
var app = angular.module('app', ['ngAria', 'ui.grid']);

浏览器支持状态

规格 支持

浏览器 操作系统 应用程序 核心 分页 单元格导航
Chrome OSX Voice Over 全部支持 全部支持 不一致的读取单元格导航。
Firefox OSX Voice Over 仅页眉/菜单 全部支持 没有,不读取。
Safari OSX Voice Over 全部支持 全部支持 全部支持


为什么只有 osx?因为它是表格测试的唯一工具。如果你用其他东西来测试过它,可以随时更新这份文件。

用 OSX 的声音测试
可以通过⌘+F5来开启声音测试。设置修改声音自动跟随鼠标,将使声音控制光标移动到要开始导航的位置更容易。或者, 您也可以使用声音导航到表,在表格中管理焦点,以便在添加和移除菜单以及禁用按钮时,声音的光标保持不变。

测试没有 OSX 的声音
只需使用 tab 和 shift + tab 键即可在网格上导航菜单和按钮。

可视化辅助功能
您可以使用这个简单的 javascript 可视化小工具应用到表格的辅助功能:http://khan.github.io/tota11y/

代码:
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="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.16/angular-aria.js"></script>
    <script src="app.js"></script>
  </head>
  <body>
    <div role="application" ng-controller="MainCtrl">
      <h3 id="example_short-dataset-without-virtualization">Short Dataset without Virtualization</h3>
      <button type="button" name="Set focus button" class="btn btn-default">Set Focus Here</button></br></br>
      <div id="grid1" ui-grid="smallGrid" class="grid1"></div>
      </br>
      <h3 id="example_long-dataset-with-virtualization">Long Dataset with Virtualization</h3>
      <button type="button" name="Set focus button" class="btn btn-default">Set Focus Here</button></br></br>
      <div id="grid2" ui-grid="virtualGridOptions" ui-grid-cellnav class="grid2" aria-labelledby="grid2-label"></div>
      <label id="grid2-label">A large list of people and the companies they work for.</label>
      <p>
        The above example only allows the screen reader to read the data that is currently visible.
        Since the browser has no knowledge about the location of the screen reader cursor the grid
        never scrolls.
        The plan for the future is to integrate cell nav with the aria labels so that the screen
        reader dictates where the user is on the grid.
      </p>
      </br>
      <h3 id="example_long-dataset-with-virtualization-and-pagination">Long Dataset with Virtualization and Pagination</h3>
      <button type="button" name="Set focus button" class="btn btn-default">Set Focus Here</button></br></br>
      <div id="grid3" ui-grid="paginationGridOptions" class="grid3" ui-grid-pagination aria-labelledby="grid3-label"></div>
      <label id="grid3-label">A large list of people and the companies they work for using pagination controls.</label>
    </div>
  </body>
</html>

main.css

.grid1 {
  width: 700px;
  height: 300px;
}
.grid2 {
  width: 700px;
  height: 400px;
}
.grid3 {
  width: 700px;
  height: 430px;
}
.red { color: red;  background-color: yellow !important; }
.blue { color: blue;  }

app.js

var app = angular.module('app', ['ngTouch', 'ngAria', 'ui.grid', 'ui.grid.pagination', 'ui.grid.cellNav']);

app.controller('MainCtrl', ['$scope', '$http', 'uiGridConstants', function ($scope, $http, uiGridConstants) {
  var setGender = function ( row, index ){
    row.gender = row.gender==='male' ? '1' : '2';
  };
  $scope.smallGrid = {
    enableSorting: true,
    showGridFooter: true,
    enableGridMenu: true,
    enableFiltering: true,
    columnDefs: [
      { field: 'firstName'},
      {
        field: 'lastName',
        filter: {
          placeholder: 'set sr focus here',
          ariaLabel: 'I have a custom aria label for this field.'
        }
      },
      {
        field: 'gender',
        filter: {
          type: uiGridConstants.filter.SELECT,
          selectOptions: [
            {value: '1', label: 'male'},
            {value: '2', label: 'female'},
          ],
        },
        cellFilter: 'mapGender'
      },
      { field: 'company' },
      { field: 'employed'},
    ],
    data: [
      {
          "firstName": "Cox",
          "lastName": "Carney",
          "gender": 1,
          "company": "Enormo",
          "employed": true
      },
      {
          "firstName": "Lorraine",
          "lastName": "Wise",
          "gender": 2,
          "company": "Comveyer",
          "employed": false
      },
      {
          "firstName": "Nancy",
          "lastName": "Waters",
          "gender": 2,
          "company": "Fuelton",
          "employed": false
      }
    ],
  };


  $scope.virtualGridOptions = {
    enableSorting: true,
    showGridFooter: true,
    enableFiltering: true,
    modifierKeysToMultiSelectCells: true,
    columnDefs: [
      { field: 'name'},
      { field: 'company'},
      { field: 'gender', cellTooltip: true, headerTooltip: true, cellFilter: 'mapGender' },
    ],
    onRegisterApi: function( gridApi ) {
      $scope.gridApi = gridApi;
      $scope.gridApi.core.on.sortChanged( $scope, function( grid, sort ) {
        $scope.gridApi.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );
      })
    }
  };
  $scope.paginationGridOptions = {
    paginationPageSizes: [10, 25, 50, 75],
    paginationPageSize: 10,
  };
  angular.extend($scope.paginationGridOptions, $scope.virtualGridOptions);

  $http.get('http://ui-grid.info/data/100.json')
    .success(function(data) {
      data.forEach(setGender);
      $scope.virtualGridOptions.data = data;
      $scope.paginationGridOptions.data = data;
    });
}])
.filter('mapGender', function() {
  var genderHash = {
    1: 'male',
    2: 'female'
  };

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

作者水平有限,不当之处敬请指正。
感谢您的阅读,如果觉得文章对您有帮助,请支持一下。

原文:121 Grid Menu

表格菜单栏可以通过gridOption 中设置 enableGridMenu: true 来开启。这将在表格的右上方添加一个图标,该图标浮动在列标题的上方。默认菜单可以显示/隐藏列,还可以自定义额外的动作。

每个菜单项都可以自定义功能:

shown:一个function,用来决定该项是否显示的
title:菜单项显示的标题(注意,也可以使用 i18n 通过 gridMenuTitleFilter 设置)
icon:显示在项目旁边的图标
action:当菜单被点击时将被调用的function
active:一个function,用来高亮显示该项()
context:默认情况下,action、shown 和 active 的上下文将作为属性添加到grid 中,菜单项可以通过this.context添加上下文属性来传递自己的上下文。
leaveOpen:默认是false,如果设置为true,将在菜单操作后打开
order:菜单中项目的顺序。列300 -> 300 + numColumns ×2,导入和导出分别为150和200
导出功能还向该菜单添加菜单项。exporterMenuCsv设置为false,可以禁用CSV的导出。如果选择了一行,则只提供“导出选择行”选项。

列标题可以使用gridMenuTitleFilter自定义筛选器来定义,当你有一个国际化的两列标题,你也希望它们在表格菜单中国际化,翻译需要返回一个字符串或者一个deferred.promise的字符串。在下面的例子中,我们创建了一个假国际化函数,等待1秒,然后用”col: “连接。

可以通过gridMenuShowHideColumns: false来关闭 gridOption 显示和隐藏列的功能,也可以通过设置enableHiding 来关闭columnDef 显示和隐藏单个列的功能。

gridMenu 的按钮还是有点丑。可以在CSS中覆盖适合应用程序的高度:

.ui-grid-menu-button {
  height: 31px;
}

代码:
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">
      <div id="grid1" ui-grid="gridOptions" ui-grid-exporter ui-grid-selection class="grid"></div>
      <div ng-if='columnChanged'>
        Column Visibility Changed - name: {{ columnChanged.name }} visible: {{ columnChanged.visible }}
      </div>
    </div>
  </body>
</html>

mian.css

.grid {
  width: 500px;
  height: 400px;
}

.my-custom-menu {
  position: absolute;
}

.my-custom-menu .ui-grid-menu {
  padding: 0px;
}

.my-custom-menu .ui-grid-menu-inner {
  -webkit-box-shadow: none;
  box-shadow: none;
}

.rotated {
  transform: rotate(180deg);
  -webkit-transform: rotate(180deg);
  -ms-transform: rotate(180deg);
  -moz-transform: rotate(180deg);
  -o-transform: rotate(180deg);
}

app.js

var app = angular.module('app', ['ngTouch', 'ui.grid', 'ui.grid.exporter', 'ui.grid.selection']);

app.controller('MainCtrl', ['$scope', '$http', '$interval', '$q', function ($scope, $http, $interval, $q) {
  var fakeI18n = function( title ){
    var deferred = $q.defer();
    $interval( function() {
      deferred.resolve( 'col: ' + title );
    }, 1000, 1);
    return deferred.promise;
  };

  $scope.gridOptions = {
    exporterMenuCsv: false,
    enableGridMenu: true,
    gridMenuTitleFilter: fakeI18n,
    columnDefs: [
      { name: 'name' },
      { name: 'gender', enableHiding: false },
      { name: 'company' }
    ],
    gridMenuCustomItems: [
      {
        title: 'Rotate Grid',
        action: function ($event) {
          this.grid.element.toggleClass('rotated');
        },
        order: 210
      }
    ],
    onRegisterApi: function( gridApi ){
      $scope.gridApi = gridApi;

      // interval of zero just to allow the directive to have initialized
      $interval( function() {
        gridApi.core.addToGridMenu( gridApi.grid, [{ title: 'Dynamic item', order: 100}]);
      }, 0, 1);

      gridApi.core.on.columnVisibilityChanged( $scope, function( changedColumn ){
        $scope.columnChanged = { name: changedColumn.colDef.name, visible: changedColumn.colDef.visible };
      });
    }
  };

  $http.get('http://ui-grid.info/data/100.json')
    .success(function(data) {
      $scope.gridOptions.data = data;
    });
}]);

Demo

作者水平有限,不当之处敬请指正。
感谢您的阅读,如果觉得文章对您有帮助,请支持一下。

原文:117 Tooltips

当用户悬停在单元格上时,可以设置工具提示。

在columnDef 中设置 cellTooltip: true 后,此工具提示可以简单的单元格内容。

或者,它可以接收function 返回的当前列和行的值,例如:

cellTooltip: function(row, col) {
    return 'Name: ' + row.entity.name + ' Company: ' + row.entity.company;
  }

或者它可以是一个字符串,在这种情况下,字符串将显示:

cellTooltip: 'Custom tooltip - maybe some help text'

也可以用类似的方法设置一个headerTooltip ,默认是显示的是displayName。

注意,打开工具提示将会为每个单元格创建一个额外的监控,因此对表格整体性能会造成影响,不建议把他们对每一列,比如列有数据但在表格中不显示(如长描述字段)。

Tooltips 优先于cellFilter,所以如果定义了一个cellFilter 也可以用工具提示。

代码:
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">
      <br>
      <br>
      <div id="grid1" ui-grid="gridOptions" class="grid"></div>
    </div>
  </body>
</html>

main.css

.grid {
  width: 500px;
  height: 200px;
}
.red { color: red;  background-color: yellow !important; }
.blue { color: blue;  }

app.js

var app = angular.module('app', ['ngAnimate', 'ngTouch', 'ui.grid']);

app.controller('MainCtrl', ['$scope', '$http', 'uiGridConstants', function ($scope, $http, uiGridConstants) {
  $scope.gridOptions = {
    enableSorting: true,
    columnDefs: [
      { field: 'name', cellTooltip: 'Custom string', headerTooltip: 'Custom header string' },
      { field: 'company', cellTooltip: 
        function( row, col ) {
          return 'Name: ' + row.entity.name + ' Company: ' + row.entity.company;
        }, headerTooltip: 
        function( col ) {
          return 'Header: ' + col.displayName;
        }
      },
      { field: 'gender', cellTooltip: true, headerTooltip: true, cellFilter: 'mapGender' },
    ],
    onRegisterApi: function( gridApi ) {
      $scope.gridApi = gridApi;
      $scope.gridApi.core.on.sortChanged( $scope, function( grid, sort ) {
        $scope.gridApi.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );
      })
    }
  };

  $http.get('http://ui-grid.info/data/100.json')
    .success(function(data) {
      data.forEach( function setGender( row, index ){
        row.gender = row.gender==='male' ? '1' : '2';
      });

      $scope.gridOptions.data = data;
    });
}])
.filter('mapGender', function() {
  var genderHash = {
    1: 'male',
    2: 'female'
  };

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

Demo

作者水平有限,不当之处敬请指正。
感谢您的阅读,如果觉得文章对您有帮助,请支持一下。

原文: 115 HeaderCellClass

在columnDef中可以为每个列表头 设置一个class名称或者通过function返回的一个class名称。

在下面例子中,我们可以设置第一列的字体颜色为蓝色,第二列当排序条件为ASC时字体颜色和背景色改变。

代码:
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">
      <br>
      <br>
      <div id="grid1" ui-grid="gridOptions" class="grid"></div>
    </div>
  </body>
</html>

main.css

.grid {
  width: 500px;
  height: 200px;
}
.red { color: red;  background-color: yellow !important; }
.blue { color: blue;  }

app.js

var app = angular.module('app', ['ngAnimate', 'ngTouch', 'ui.grid']);

app.controller('MainCtrl', ['$scope', '$http', 'uiGridConstants', function ($scope, $http, uiGridConstants) {
  $scope.gridOptions = {
    enableSorting: true,
    columnDefs: [
      { field: 'name', headerCellClass: 'blue' },
      { field: 'company',
        headerCellClass: function(grid, row, col, rowRenderIndex, colRenderIndex) {
          if (col.sort.direction === uiGridConstants.ASC) {
            return 'red';
          }
        }
      }
    ],
    onRegisterApi: function( gridApi ) {
      $scope.gridApi = gridApi;
      $scope.gridApi.core.on.sortChanged( $scope, function( grid, sort ) {
        $scope.gridApi.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );
      })
    }
  };

  $http.get('http://ui-grid.info/data/100.json')
    .success(function(data) {
      $scope.gridOptions.data = data;
    });
}]);

Demo

作者水平有限,不当之处敬请指正。
感谢您的阅读,如果觉得文章对您有帮助,请支持一下。

原文:114 Adding a row header

可以添加行标题列,它会固定在表格容器的左边。

代码:
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">
      <div id="grid1" ui-grid="gridOptions" class="grid"></div>
    </div>
  </body>
</html>

main.css

.grid {
  width: 500px;
  height: 250px;
}

app.js

var app = angular.module('app', ['ngAnimate', 'ngTouch', 'ui.grid']);

app.controller('MainCtrl', ['$scope', '$http', function ($scope, $http) {
  $scope.columns = [{ field: 'name' }, { field: 'gender' }];
  $scope.gridOptions = {
    enableSorting: true,
    columnDefs: $scope.columns,
    onRegisterApi: function( gridApi ) { 
      $scope.gridApi = gridApi;
      var cellTemplate = 'ui-grid/selectionRowHeader';   // you could use your own template here
      $scope.gridApi.core.addRowHeaderColumn( { name: 'rowHeaderCol', displayName: '', width: 30, cellTemplate: cellTemplate} );
    }
  };

  $http.get('http://ui-grid.info/data/100.json')
    .success(function(data) {
      $scope.gridOptions.data = data;
      console.log(data)
    });
}]);

Demo

作者水平有限,不当之处敬请指正。
感谢您的阅读,如果觉得文章对您有帮助,请支持一下。

原文: 113 Adding and removing columns

表格会监控column defs 和 数据的更新,你可以动态地添加和删除列。列默认的显示顺序是按照columnDefs的顺序,用户可以通过移动表格的列来改变默认的顺序。

动态更改列上的显示名称(以及其他一些列属性),可以通过notifyDataChange API来强制更新。

代码:
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">
      Try clicking the Add button to add the company column.
      Try clicking the Remove button to remove the last column.
      Try clicking the Splice button to insert a column in the middle.
      <br>
      <br>
      <button id="button_add" class="btn" ng-click="add()">Add</button>
      <button id="button_remove" class="btn" ng-click="remove()">Remove Last</button>
      <button id="button_splice" class="btn" ng-click="splice()">Splice</button>
      <button id="button_unsplice" class="btn" ng-click="unsplice()">Remove Middle</button>
      <button id="button_toggle_visible" class="btn" ng-click="toggleVisible()">Toggle Visible</button>
      <button id="button_toggle_display_name" class="btn" ng-click="toggleDisplayName()">Toggle Display Name</button>
      <div id="grid1" ui-grid="gridOptions" class="grid"></div>
    </div>
  </body>
</html>

main.css

.grid {
  width: 500px;
  height: 250px;
}

app.js

var app = angular.module('app', ['ngAnimate', 'ngTouch', 'ui.grid']);

app.controller('MainCtrl', ['$scope', '$http', 'uiGridConstants', function ($scope, $http, uiGridConstants) {
  $scope.columns = [{ field: 'name' }, { field: 'gender' }];
  $scope.gridOptions = {
    enableSorting: true,
    columnDefs: $scope.columns,
    onRegisterApi: function(gridApi) {
      $scope.gridApi = gridApi;
    }
  };

  $scope.remove = function() {
    $scope.columns.splice($scope.columns.length-1, 1);
  }

  $scope.add = function() {
    $scope.columns.push({ field: 'company', enableSorting: false });
  }

  $scope.splice = function() {
    $scope.columns.splice(1, 0, { field: 'company', enableSorting: false });
  }

  $scope.unsplice = function() {
    $scope.columns.splice(1, 1);
  }

  $scope.toggleDisplayName = function() {
    if( $scope.columns[1].displayName === 'GENDER' ){
      $scope.columns[1].displayName = 'Gender';
    } else {
      $scope.columns[1].displayName = 'GENDER';
    }
    $scope.gridApi.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );
  }

  $scope.toggleVisible = function() {
    $scope.columns[0].visible = !($scope.columns[0].visible || $scope.columns[0].visible === undefined);
    $scope.gridApi.core.notifyDataChange(uiGridConstants.dataChange.COLUMN);
  }

  $http.get('http://ui-grid.info/data/100.json')
    .success(function(data) {
      $scope.gridOptions.data = data;
    });
}]);

Demo

作者水平有限,不当之处敬请指正。
感谢您的阅读,如果觉得文章对您有帮助,请支持一下。