Fab*_*ien 38 angularjs ng-grid
我的用例非常简单.在编辑Cell(enableCellEdit:true)之后,用户应该将数据"自动"发送到服务器(在单元格模糊时).我尝试了不同的方法,但没有一个方法得到适当的解决.我有一个简约的网格:
// Configure ng-grid
$scope.gridOptions = {
data: 'questions',
enableCellSelection: true,
selectedItems: $scope.selectedRow,
multiSelect: false,
columnDefs: [
{field: 'id', displayName: 'Id'},
{field: 'name', displayName: 'Name'},
{field: 'answers[1].valuePercent', displayName: 'Rural', enableCellEdit: true}
]
};
Run Code Online (Sandbox Code Playgroud)
例如,我试图观察传递给Grid的数据模型.但这样做不会返回我编辑的单元格:
$scope.$watch('myData', function (foo) {
// myModel.$update()
}, true);
Run Code Online (Sandbox Code Playgroud)
我试图摆弄"ngGridEventData"数据事件,但在单元格编辑后它不会触发
$scope.$on('ngGridEventData', function (e, gridId) {
// myModel.$update()
});
Run Code Online (Sandbox Code Playgroud)
最后,我试图观察一个Cell.但是,这仅适用于网格的"selectedCell"属性的行:
$scope.selectedRow = [];
$scope.gridOptions = {
selectedItems: $scope.selectedRow,
}
$scope.$watch('selectedRow', function (foo) {
console.log(foo)
}, true);
Run Code Online (Sandbox Code Playgroud)
它是否需要ng-grid插件?我不敢相信它不是开箱即用的东西.
你有一个指针/片段如何解决自动保存/发送到服务器?
小智 30
也许这是新的,但ng-grid实际上发布了可用于实现简单的更改更新的事件.
事件参考:https://github.com/angular-ui/ng-grid/wiki/Grid-Events
示例代码(添加到设置网格的控制器):
$scope.$on('ngGridEventEndCellEdit', function(evt){
console.log(evt.targetScope.row.entity); // the underlying data bound to the row
// Detect changes and send entity to server
});
Run Code Online (Sandbox Code Playgroud)
需要注意的一点是,即使没有进行任何更改,事件也会触发,因此您可能仍希望在发送到服务器之前检查更改(例如,通过'ngGridEventStartCellEdit')
Mic*_*kin 21
我发现了我认为更好的解决方案:
cellEditableTemplate = "<input ng-class=\"'colt' + col.index\" ng-input=\"COL_FIELD\" ng-model=\"COL_FIELD\" ng-change=\"updateEntity(row.entity)\"/>"
Run Code Online (Sandbox Code Playgroud)
以这种方式使用ng-change将导致使用已更改的整个对象(行)调用updateEntity,并将其发布回服务器.您不需要任何新的范围变量.之前解决方案的一个缺点是,当您单击开始编辑字段时,在开始编辑之前,它将始终为空白而不是原始值.
这将导致每次击键时调用updateEntity().如果这对您来说太频繁,您可以在发布到服务器之前使用超时,或者只使用updateEntity()来记录您想要推送的ID,然后使用ng-blur发布记录的ID.
Fab*_*ien 17
看起来我找到了一个解决方案,感谢Angular 邮件列表.有人指出AngularJS缺少onBlur事件(以及onFocus).但是,这可以通过添加"简单"指令来克服.
angular.module('myApp.ngBlur', [])
.directive('ngBlur', function () {
return function (scope, elem, attrs) {
elem.bind('blur', function () {
scope.$apply(attrs.ngBlur);
});
};
});
Run Code Online (Sandbox Code Playgroud)
随着信息,还有相关的模糊事件指令执行的另一个例子在这里.
然后,控制器中的其余代码如下所示:
// Define the template of the cell editing with input type "number" (for my case).
// Notice the "ng-blur" directive
var cellEditableTemplate = "<input style=\"width: 90%\" step=\"any\" type=\"number\" ng-class=\"'colt' + col.index\" ng-input=\"COL_FIELD\" ng-blur=\"updateEntity(col, row)\"/>";
// Configure ng-grid
$scope.gridOptions = {
data: 'questions',
enableCellSelection: true,
multiSelect: false,
columnDefs: [
{field: 'id', displayName: 'Id'},
{field: 'name', displayName: 'Name'},
// Notice the "editableCellTemplate"
{field: 'answers[0].valuePercent', displayName: 'Rural', enableCellEdit: true, editableCellTemplate: cellEditableTemplate}
]
};
// Update Entity on the server side
$scope.updateEntity = function(column, row) {
console.log(row.entity);
console.log(column.field);
// code for saving data to the server...
// row.entity.$update() ... <- the simple case
// I have nested Entity / data in the row <- the complex case
// var answer = new Answer(question.answers[answerIndex]); // answerIndex is computed with "column.field" variable
// answer.$update() ...
}
Run Code Online (Sandbox Code Playgroud)
我花了一些时间将这些部分用于ng-grid 2.x.我仍然有一个问题,必须点击两次编辑一行,但我认为这是一个引导问题,而不是一个ngGrid问题,它不会发生在我的示例代码中(它还没有引导程序).
我还在ui-grid 3.0的教程中实现了类似的逻辑,它仍然是测试版,但很快就会成为首选版本.可以在以下网址找到:http://technpol.wordpress.com/2014/08/23/upgrading-to-ng-grid-3-0-ui-grid/,并为此功能提供更简单,更清晰的API .
对于2.x版本,为了说明所有的比特,我创建了一个运行的plunker,它有一个带有下拉列表和输入字段的可编辑网格,使用ngBlur指令,并使用$ timeout来避免重复保存.更新:http://plnkr.co/edit/VABAEu?p = preview
代码的基础是:
var app = angular.module('plunker', ["ngGrid"]);
app.controller('MainCtrl', function($scope, $timeout, StatusesConstant) {
$scope.statuses = StatusesConstant;
$scope.cellInputEditableTemplate = '<input ng-class="\'colt\' + col.index" ng-input="COL_FIELD" ng-model="COL_FIELD" ng-blur="updateEntity(row)" />';
$scope.cellSelectEditableTemplate = '<select ng-class="\'colt\' + col.index" ng-input="COL_FIELD" ng-model="COL_FIELD" ng-options="id as name for (id, name) in statuses" ng-blur="updateEntity(row)" />';
$scope.list = [
{ name: 'Fred', age: 45, status: 1 },
{ name: 'Julie', age: 29, status: 2 },
{ name: 'John', age: 67, status: 1 }
];
$scope.gridOptions = {
data: 'list',
enableRowSelection: false,
enableCellEditOnFocus: true,
multiSelect: false,
columnDefs: [
{ field: 'name', displayName: 'Name', enableCellEditOnFocus: true,
editableCellTemplate: $scope.cellInputEditableTemplate },
{ field: 'age', displayName: 'Age', enableCellEdit: false },
{ field: 'status', displayName: 'Status', enableCellEditOnFocus: true,
editableCellTemplate: $scope.cellSelectEditableTemplate,
cellFilter: 'mapStatus'}
]
};
$scope.updateEntity = function(row) {
if(!$scope.save) {
$scope.save = { promise: null, pending: false, row: null };
}
$scope.save.row = row.rowIndex;
if(!$scope.save.pending) {
$scope.save.pending = true;
$scope.save.promise = $timeout(function(){
// $scope.list[$scope.save.row].$update();
console.log("Here you'd save your record to the server, we're updating row: "
+ $scope.save.row + " to be: "
+ $scope.list[$scope.save.row].name + ","
+ $scope.list[$scope.save.row].age + ","
+ $scope.list[$scope.save.row].status);
$scope.save.pending = false;
}, 500);
}
};
})
.directive('ngBlur', function () {
return function (scope, elem, attrs) {
elem.bind('blur', function () {
scope.$apply(attrs.ngBlur);
});
};
})
.filter('mapStatus', function( StatusesConstant ) {
return function(input) {
if (StatusesConstant[input]) {
return StatusesConstant[input];
} else {
return 'unknown';
}
};
})
.factory( 'StatusesConstant', function() {
return {
1: 'active',
2: 'inactive'
};
});
Run Code Online (Sandbox Code Playgroud)
当您运行此plunker并且失去焦点时,您应该在控制台上看到更新触发器触发.
我还在plunker中包含了一个README.md,其中有一些关于让我困难的事情的想法,在这里再现.
这里的功能是我有一个人名单,那些人有姓名,年龄和状态.与我们在真实应用程序中可能执行的操作一致,状态是代码,我们希望显示解码.因此,我们有一个状态代码列表(可能在真正的应用程序中来自数据库),我们有一个过滤器将代码映射到解码.
我们想要的是两件事.我们希望能够在输入框中编辑名称,并在下拉列表中编辑状态.
评论我在这个问题上学到的东西.
在gridOptions级别,有enableCellEditOnFocus和enableCellEdit.不要同时启用,需要选择.onFocus意味着单击,CellEdit意味着双击.如果同时启用这两个,那么您不希望可编辑的网格位出现意外行为
在columnDefs级别,您有相同的选项.但是这次你需要设置CellEdit和onFocus,你需要在你不想编辑的任何单元格上将cellEdit设置为false - 这不是默认
文档说您的可编辑单元格模板可以是:
<input ng-class ="'colt'+ col.index"ng-input ="COL_FIELD"/>
实际上它需要是:
<input ng-class ="'colt'+ col.index"ng-input ="COL_FIELD"ng-model ="COL_FIELD"/>
为了在失去焦点时触发保存事件,我们创建了一个模糊指令,我在stackoverflow中找到的逻辑:AngularJS和ng-grid - 在单元格更改后自动将数据保存到服务器
这也意味着更改每个可编辑单元格模板以调用ng-blur,您可以在可编辑单元格模板的末尾看到该模板
当我们离开现场时(至少在Chrome中)我们得到两个模糊事件,因此我们使用计时器,以便只处理其中一个.丑陋,但它的工作原理.
我还创建了一篇博文,对这段代码进行了更全面的演练:http://technpol.wordpress.com/2013/12/06/editable-nggrid-with-both-dropdowns-and-selects/
| 归档时间: |
|
| 查看次数: |
36246 次 |
| 最近记录: |