I'm using handsontable, and I want to change the background color of a cell if its value is edited and changed. I can do this easily if my data source is an array of arrays (see fiddle: http://jsfiddle.net/chiman24/3o2c3c7m/).
document.addEventListener("DOMContentLoaded", function() {
// Row Styles
var blank = function(instance, td, row, col, prop, value,
cellProperties) {
Handsontable.renderers.TextRenderer.apply(this, arguments);
td.style.backgroundColor = '#ABAAAA'
};
var align = function(instance, td, row, col, prop, value,
cellProperties) {
Handsontable.renderers.TextRenderer.apply(this, arguments);
td.style.verticalAlign = 'middle';
td.style.fontWeight = 'bold';
};
var highlight1 = function(instance, td, row, col, prop, value,
cellProperties) {
Handsontable.renderers.TextRenderer.apply(this, arguments);
td.style.backgroundColor = '#BDD7EE';
td.style.textAlign = 'right';
};
var changedBackgroundColor = '#cbd9e4';
var defaultBackgroundColor = 'white';
var hasChanged = function(instance, td, row, col, prop, value,
cellProperties) {
Handsontable.renderers.TextRenderer.apply(this, arguments);
td.style.backgroundColor = changedBackgroundColor;
};
var noChange = function(instance, td, row, col, prop, value,
cellProperties) {
Handsontable.renderers.TextRenderer.apply(this, arguments);
td.style.backgroundColor = defaultBackgroundColor;
};
var data = [
["1", "Hear us from heaven", "New Life Worship",
"Anderson, Jared", "something"
],
["2", "Spirit Break Out", "Kim Walker", "Walker, Kim",
"Still Believe"
]
],
dataCopy = [
["1", "Hear us from heaven", "New Life Worship",
"Anderson, Jared", "something"
],
["2", "Spirit Break Out", "Kim Walker", "Walker, Kim",
"Still Believe"
]
],
container = document.getElementById('example1'),
hot1;
//Table Row and Col Options
hot1 = new Handsontable(container, {
data: data,
fixedColumnsLeft: 1,
columnSorting: true,
colHeaders: ["id", "title", "artist", "author", "album"],
columns: [{
type: "text"
}, {
type: "text"
}, {
type: "text"
}, {
type: "text"
}, {
type: "text"
}]
});
hot1.addHook('afterChange', afterChange);
function afterChange(changes, source) {
if (source == 'edit' || source == 'autofill') {
$.each(changes, function(index, element) {
var change = element;
var rowIndex = change[0];
var columnIndex = change[1];
var oldValue = change[2];
var newValue = change[3];
var cellChange = {
'rowIndex': rowIndex,
'columnIndex': columnIndex
};
if (oldValue != newValue) {
var cellProperties = hot1.getCellMeta(
rowIndex, columnIndex);
if (newValue != dataCopy[rowIndex][
columnIndex
]) {
cellProperties.renderer = hasChanged;
} else { //data changed back to original value.
cellProperties.renderer = noChange;
}
hot1.render();
}
});
}
}
});
// noSideScroll class added to fix some containers while side scrolling the table
$(window).scroll(function() {
$('.noSideScroll').css({
'left': $(this).scrollLeft()
});
});
However, when using an array of objects, I can't get it to work. (see fiddle: http://jsfiddle.net/chiman24/24mpavga/).
var data = [{
"id": 1,
"title": "First Loved Me",
"artist": "Israel and New Breed",
"author": "Houghton, Israel",
"album": "Covered: Alive In Asia"
}, {
"id": 2,
"title": "One Thing Remains",
"artist": "Israel and New Breed",
"author": "Houghton, Israel",
"album": "Covered: Alive In Asia"
}],
dataCopy = [{
"id": 1,
"title": "First Loved Me",
"artist": "Israel and New Breed",
"author": "Houghton, Israel",
"album": "Covered: Alive In Asia"
}, {
"id": 2,
"title": "One Thing Remains",
"artist": "Israel and New Breed",
"author": "Houghton, Israel",
"album": "Covered: Alive In Asia"
}],
container = document.getElementById('example1'),
hot1;
//Table Row and Col Options
hot1 = new Handsontable(container, {
data: data,
fixedColumnsLeft: 1,
columnSorting: true,
colHeaders: ["id", "title", "artist", "author", "album"],
columns: [{
data: "id"
}, {
data: "title"
}, {
data: "artist"
}, {
data: "author"
}, {
data: "album"
}]
});
hot1.addHook('afterChange', afterChange);
function afterChange(changes, source) {
if (source == 'edit' || source == 'autofill') {
$.each(changes, function(index, element) {
var change = element;
var rowIndex = change[0];
var columnIndex = change[1];
var oldValue = change[2];
var newValue = change[3];
var cellChange = {
'rowIndex': rowIndex,
'columnIndex': columnIndex
};
if (oldValue != newValue) {
var cellProperties = hot1.getCellMeta(
rowIndex, columnIndex);
if (newValue != dataCopy[rowIndex][
columnIndex
]) {
cellProperties.renderer = hasChanged;
} else { //data changed back to original value.
cellProperties.renderer = noChange;
}
hot1.render();
}
});
}
}
Is there a way to accomplish this? I want to get it working using an array of objects because my data coming from the server will be in JSON format. I've scoured the handsontable documentation for a couple of days to no avail. Any help will be much appreciated. Thanks.
I got some help from the handsontable github forum.
Apparently, if the data source is an array of objects, then when calling "getCellMeta", instead of passing in a numerical column index, you have to pass in the column index as a property like this:
hot.getCellMeta(2, hot.propToCol(columnIndex));
Here's the updated demo