I am trying to implement row move using ngHandsontable. While visually everything was working but the data source wasn't getting updated. So, I implemented "AfterRowMove" event handler to manually rearrange the data source. I implemented it as follows:-
Controller:-
var app = angular.module('appHandson', ['ngHandsontable']);
app.controller('HandsOnCtrl', ['hotRegisterer', function (hotRegisterer) {
var vm = this;
vm.rowHeaders = true;
vm.colHeaders = true;
vm.db = {
items: [
{
Company: 'XXX',
Customer: 5464,
Order: 'One',
Priority: 1
},
{
Company: 'XXX',
Customer: 5464,
Order: 'Two',
Priority: 2
},
{
Company: 'XXX',
Customer: 546433,
Order: 'Three',
Priority: 3
}
]
};
//// Following method will be called when a row is moved. In this method, I am re-arranging the data in the data source according to the changes in the UI.
vm.onAfterRowMove = function(startRow, endRow) {
if (startRow > endRow) {
var data = angular.copy(vm.db.items);
var rowChange = data[startRow];
for (var loop = startRow; loop > endRow; loop--)
{
data[loop] = data[loop - 1];
}
data[endRow] = rowChange;
vm.db.items = data;
}
else if (startRow < endRow)
{
//// re-arrange data accordingly.
}
};
}
In the html file, I have the following markup:-
<div id="body" ng-app="appHandson">
<section>
<div ng-controller="HandsOnCtrl as ctrl">
<div class="scroll-container">
<button type="button" ng-click="ctrl.addOrder()">Add Rule</button>
<hot-table hot-id="my-handsontable" manual-row-move scroll-v="auto" col-widths="100" row-headers="ctrl.rowHeaders" col-headers="ctrl.colHeaders" datarows="ctrl.db.items" on-after-row-move="ctrl.onAfterRowMove" >
<hot-column data="Company" title="'company'" read-only></hot-column>
<hot-column data="Customer" title="'customer'" read-only></hot-column>
<hot-column data="Order" title="'order'"></hot-column>
</hot-table>
</div>
<div>
After implementing the above solution, the event handler "ctrl.onAfterRowMove" re-arranges the data in the data source correctly but when Angular's next digest cycle runs (as a result of button click or by manually calling $scope.$apply()) it randomly moves the data in handsontable/grid visually. Note that the data source "ctrl.db.items" has the data in the correct order but only appears out of order visually.
So it turns out that there is no need to re-arrange data in the data-source. Handsontable has an array called "manualRowPositions" which keeps track of the row position according to whatever it is visually. For example, if row three has been moved to the the row one manualRowPositions will have following data [2,0,1]. Note that the original data source will remain as it is. When there is a need to use the row position make use of manualRowPositions array to read data from the data source.
In the above example, I have a function called "addOrder" which will read data from data source using manualRowPositions array and send that data to the server.
vm.addOrder = function () {
var finalData = [];
var hotTable = hotRegisterer.getInstance('my-handsontable');
for (var loop = 0; loop < vm.db.items.length; loop++) {
var data = vm.db.items[hotTable.manualRowPositions[loop]];
finalData.push(data);
}
//// send finalData to the server using $http
};
There is no need for AfterRowMove event handler so remove the vm.onAfterRowMove function and also change the html markup to remove the hook for the event:-
<hot-table hot-id="my-handsontable" manual-row-move scroll-v="auto" col-widths="100" row-headers="ctrl.rowHeaders" col-headers="ctrl.colHeaders" datarows="ctrl.db.items" >