My Use Case is pretty simple. A User, after editing a Cell (enableCellEdit: true), should have the data "automatically" sent to the server (on cell blur). I tried different approaches but none of them have properly worked out. I have a minimalistic grid:
// 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}
]
};
For example, I tried to watch the data model passed to the Grid. But doing so won't return me the edited cell:
$scope.$watch('myData', function (foo) {
// myModel.$update()
}, true);
I tried to fiddle with the "ngGridEventData" data event but it does not fire after cell edit
$scope.$on('ngGridEventData', function (e, gridId) {
// myModel.$update()
});
Finally, I tried to observer a Cell. However, this only work for a row by the mean of the "selectedCell" property of the grid:
$scope.selectedRow = [];
$scope.gridOptions = {
selectedItems: $scope.selectedRow,
}
$scope.$watch('selectedRow', function (foo) {
console.log(foo)
}, true);
Is it a ng-grid plugin needed? I can't believe it is not something out of the box.
Would you have a pointer / snippet how I could solve the auto save / send to the server?
If you're using UI Grid 3.0 that event is: uiGridEventEndCellEdit
I've spent some time pulling together the bits of this for ng-grid 2.x. I still have a problem with having to click twice to edit a row, but I think that's a bootstrap issue, not an ngGrid issue, it doesn't happen in my sample code (which doesn't have bootstrap yet).
I've also implemented similar logic in a tutorial for ui-grid 3.0, which is still beta but will soon become the preferred version. This can be found at: http://technpol.wordpress.com/2014/08/23/upgrading-to-ng-grid-3-0-ui-grid/, and provides a much easier and cleaner api for this functionality.
For the 2.x version, to illustrate all the bits, I've created a running plunker that has an editable grid with both a dropdown and an input field, uses the ngBlur directive, and uses a $timeout to avoid duplicate saves on the update: http://plnkr.co/edit/VABAEu?p=preview
The basics of the code are:
When you run this plunker, and the lose focus fires, you should see on the console the update trigger firing.
I also included a README.md in the plunker with some thoughts on things that gave me difficulty, reproduced here.
The functionality here is that I have a list of people, those people have names, ages and statuses. In line with what we might do in a real app, the status is a code, and we want to show the decode. Accordingly we have a status codes list (which might in a real app come from the database), and we have a filter to map the code to the decode.
What we want are two things. We'd like to be able to edit the name in an input box, and to edit the status in a dropdown.
Comments on things I've learned on this plunk.
At the gridOptions level, there are both enableCellEditOnFocus and enableCellEdit. Don't enable both, you need to pick. onFocus means single click, CellEdit means double click. If you enable both then you get unexpected behaviour on the bits of your grid you didn't want to be editable
At the columnDefs level, you have the same options. But this time you need to set both CellEdit and onFocus, and you need to set cellEdit to false on any cells you don't want edited - this isn't the default
The documentation says that your editable cell template can be:
<input ng-class="'colt' + col.index" ng-input="COL_FIELD" />
actually it needs to be:
<input ng-class="'colt' + col.index" ng-input="COL_FIELD" ng-model="COL_FIELD" />
To trigger a save event when we lose focus, we've created an blur directive, the logic for which I found in stackoverflow: AngularJS and ng-grid - auto save data to the server after a cell was changed
This also means changing each editable cell template to call ng-blur, which you can see at the end of the editable cell template
We get two blur events when we leave the field (at least in Chrome), so we use a timer so that only one of them is processed. Ugly, but it works.
I've also created a blog post that does a more thorough walkthrough of this code: http://technpol.wordpress.com/2013/12/06/editable-nggrid-with-both-dropdowns-and-selects/
This is an improvement to the answer which has a few flaws: - it triggers a JS exception, as indicated in one of answer's comments - the data input in the cell is not retained in the grid - the updateEntity method does not illustrate how to save the input data
In order to remove the exception, create a scope attribute and add it to cellEditableTemplate:
Notice that the ng-blur call to updateEntity now includes cellValue as an argument. Next, update the updateEntity blur handler to include the argument and update the grid:
I'm now able to see the changes on the screen as well as to trigger cell-based back-end updates.
As PaulL mentioned in one of the comments ui-grid now has a rowEdit feature designed to allow saving of the entire row when done editing. See http://ui-grid.info/docs/#/tutorial/205_row_editable.
Maybe this is new but ng-grid actually publishes events which can be used to implement a simple update on change.
Event Reference: https://github.com/angular-ui/ng-grid/wiki/Grid-Events
Example code (add to controller where you setup the grid):
One thing to note is that the event will trigger even if no changes have been made, so you may still want to check for changes before sending to the server (for example via 'ngGridEventStartCellEdit')
It looks I found a solution thanks to the Angular mailing list. It was pointed that AngularJS is missing the onBlur event (as well as the onFocus). However, this can be overcome by adding a "simple" directive.
As information, there is another example of implementation related to the blur event directive here.
Then, the rest of the code in the controller looks like: