ui.grid.rowedit 扩展了编辑功能, 以支持对服务器保存数据的回调, 该数据同时保存了 “行”。此功能尝试给用户一个类似于 电子表格 的体验, 以便他们可以编辑他们希望的任何字段, 并且该功能将试图保存数据 “行”。在数据不会产生错误的程度上, 从用户的角度来看, 保存过程几乎是无形的–保存后变灰色, 和不能编辑的灰色, 用户就像数据是本地的一样进行编辑。
rowEdit 功能的文档在 api 文档中提供, 特别是:
- gridOptions
- publicApi
每一行在任何时间点都是四状态之一:
- clean:未进行编辑 (或自上次保存后没有编辑)
- isDirty:已进行编辑, 但数据尚未保存, 因为用户仍在编辑该行, 或者因为计时器尚未触发
- isSaving:保存此行的回调已被调用, 尚未返回。此行在这段时间内不可编辑, 并显示为灰色, 以避免用户再次编辑行导致锁定异常
- isError:保存回调返回了一个错误。该行仍显示已更新的数据, 但将显示为红色
基本的操作方法是, 每当编辑单元格时 (使用 “编辑” 标识), 就会在该行上设置一个 isdirty 标志, 并设置一个 saveTimer。如果同一行中的另一个单元格在2秒钟内开始编辑 (或其他可配置的时间), 则计时器将再次被销毁。否则, 在完成该行的计时器将设置为 isSaving 和灰色的状态, 并且将调用 saveRow 事件。此事件调用的函数必须调用 rowEdit. setSavePromise, rowEdit 功能将等待该异步。
如果还启用了 cellNav 功能, 则该行内单元格上的 setFocus 就足以延迟计时器 (更容易地处理某些列是可编辑的情况, 用户选项卡或单击同一行上的 non-editable 字段)。
如果成功执行了该异步, 则该行将被设置回clean。如果异步被拒绝, 则该行设置为 isError的状态。
或者, 调用应用程序可以请求 flushDirtyRows, 这将触发所有当前行的脏检查保存事件。如果 rowEditWaitInterval grid option设置为-1, 那么保存将永远不会由计时器触发, 并且只在手动调用时触发。
提供的方法和属性以此制度操作:
- getDirtyRows(): 返回当前所有行脏检查的 gridRows 数组
- getErrorRows():返回所有当前错误行的 gridRows 数组
- flushDirtyRows(): 将当前所有行的脏检查 刷新到服务器, 可能在页面导航请求或按保存按钮时使用
- saveRow( rowEntity ): 当行准备保存时调用的事件
- rowEditWaitInterval: grid option控制在触发保存之前等待的时间 (ms)
在本示例中, 行在移开后2秒钟保存, 而保存是伪造的, 使用超时为3秒, 因此每个保存都需要3秒钟才能完成。性别为"male"行的保存都会出错。
代码:
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="/release/ui-grid.js"></script>
<script src="/release/ui-grid.css"></script>
<script src="app.js"></script>
</head>
<body>
<div ng-controller="MainCtrl">
<div ui-grid="gridOptions" ui-grid-edit ui-grid-row-edit ui-grid-cellNav class="grid"></div>
</div>
</body>
</html>
main.css
.grid {
width: 600px;
height: 450px;
}
app.js
var app = angular.module('app', ['ngTouch', 'ui.grid', 'ui.grid.edit', 'ui.grid.rowEdit', 'ui.grid.cellNav', 'addressFormatter']);
angular.module('addressFormatter', []).filter('address', function () {
return function (input) {
return input.street + ', ' + input.city + ', ' + input.state + ', ' + input.zip;
};
});
app.controller('MainCtrl', ['$scope', '$http', '$q', '$interval', function ($scope, $http, $q, $interval) {
$scope.gridOptions = {};
$scope.gridOptions.columnDefs = [
{ name: 'id', enableCellEdit: false },
{ name: 'name', displayName: 'Name (editable)' },
{ name: 'gender' },
{ name: 'age', displayName: 'Age' , type: 'number'},
{ name: 'registered', displayName: 'Registered' , type: 'date', cellFilter: 'date:"yyyy-MM-dd"'},
{ name: 'address', displayName: 'Address', type: 'object', cellFilter: 'address'},
{ name: 'address.city', displayName: 'Address (even rows editable)',
cellEditableCondition: function($scope){
return $scope.rowRenderIndex%2
}
},
{ name: 'isActive', displayName: 'Active', type: 'boolean'}
];
$scope.saveRow = function( rowEntity ) {
// create a fake promise - normally you'd use the promise returned by $http or $resource
var promise = $q.defer();
$scope.gridApi.rowEdit.setSavePromise( rowEntity, promise.promise );
// fake a delay of 3 seconds whilst the save occurs, return error if gender is "male"
$interval( function() {
if (rowEntity.gender === 'male' ){
promise.reject();
} else {
promise.resolve();
}
}, 3000, 1);
};
$scope.gridOptions.onRegisterApi = function(gridApi){
//set gridApi on scope
$scope.gridApi = gridApi;
gridApi.rowEdit.on.saveRow($scope, $scope.saveRow);
};
$http.get('/data/500_complex.json')
.success(function(data) {
for(i = 0; i < data.length; i++){
data[i].registered = new Date(data[i].registered);
}
$scope.gridOptions.data = data;
});
}]);
Demo
文章来源:西柚叨叨的个人博客