I am trying to implement Handsontable into our reporting system. Ive done everything i wanted except one thing. I am highlighting error cell using renderers (simply by setting red color on background). However when i remove row by context menu->remove row, all renderers remain on their x-y positions. I'd like them to follow their rows instead.
$container.handsontable({
data: data,
rowHeaders: true,
colHeaders: true,
minSpareRows: 1,
contextMenu: true,
stretchH: 'all',
comments: true,
cells: function(row, col, prop) {
var cellProperties = {};
{foreach $excelError as $error}
if (row === {$error['row']} && col === {$error['col']}) {
cellProperties.renderer = {$error['renderer']};
cellProperties.comment = {$error['desc']};
}
{/foreach}
if (row === 0) {
cellProperties.renderer = firstRowRenderer;
}
return cellProperties;
}
});
Despite variable name $error it also contents correct row data which just pain cells with white color. The errorRenderer function looks like this (white one is similar to this one)
var errorRenderer = function(instance, td, row, col, prop, value, cellProperties) {
Handsontable.renderers.TextRenderer.apply(this, arguments);
$(td).css({
background: 'red',
color: "white",
fontWeight: "bold"
});
};
Any idea how to fix that? I'd be fine even just with catch of that remove row event as i can call ajax and rerender cells again.
Thank you for any ideas.
EDIT:
Fixed solution:
var cellsProp = new Array();
{foreach $excelError as $error}
cellsProp[{$error['row']}] = new Array();
cellsProp[{$error['row']}][{$error['col']}] = {$error['renderer']|noescape};
{/foreach}
var removing = false;
$container.handsontable({
data: data,
rowHeaders: true,
colHeaders: true,
minSpareRows: 1,
contextMenu: true,
stretchH: 'all',
comments: true,
cells: function(row, col, prop) {
var cellProperties = {};
if (typeof cellsProp[row] != "undefined") {
cellProperties.renderer = cellsProp[row][col];
}
if (row === 0) {
cellProperties.renderer = firstRowRenderer;
}
return cellProperties;
},
beforeRemoveRow: function(index, amount) {
if (removing == false) {
for (x = index; x < cellsProp.length; x++) {
cellsProp[x] = cellsProp[x+1];
}
}
removing = true;
},
afterRemoveRow: function(index, amount) {
removing = false;
}
});
The error is in the PHP. When a row is deleted, your PHP still thinks that a specific row index is in error. If you could you provide a function that would remove a row from your PHP, we can create a function beforeRemoveRow
which triggers after a row is removed.
In here we can call your PHP function and give it the row index to remove. Your program should now work.
The function would look like this, and would be added to the list of options on your hot definition:
beforeRemoveRow: function(index, amount) {
phpFunctionRemoveRow(index);
}
EDIT:
With this logic of hard-coded coordinates, removing a row would always give you the behavior of turning (x,y) red. This is what was meant by having an "error" in your php. It means that since you receive the coordinates with errors from PHP, you can't expect the hardcoded index values to change.
Something still doesn't make sense. If you have no interaction with PHP after render (you don't call it after render), and you say that PHP is correct, then does this mean you're never going to be modifying your table? What if someone makes a change and you have to re-validate your table?
If, however, you are capable of doing this, then what I would do is the following:
After a change to the table, call your php function to revalidate. This will change that errors array you have in php but because the cells
option is static, you won't see changes. At that point, you'd use:
hotInstance.updateSettings({ cells: getCellsAgain() });
In that function, getCellsAgain()
, you'd call your php code again to tell you the new indeces. That's the best you'll get without doing the validation on the JS side.