I'd like to be able to edit the text of column headers in a Handsontable but I can't seem to figure out if it's possible to make them editable. I suppose I could make the headers just another row, but I'd like to avoid that if at all possible.
To clarify: I'm actually looking for a way to allow the user to edit the header values (as they would a normal table cell
# Overview. Column headers are gray-colored rows used to label each column or group of columns. By default, these headers are populated with letters in alphabetical order. To reflect the type or category of data in a particular column, give it a custom name and then display it in a column header.
This is probably too late for OP but anybody else looking for the same answer you can change the column headers (as well as other settings) after the table has already been rendered with the following:
var hot = $container.data('handsontable'); hot.updateSettings({ colHeaders: ['A','B','C'] });
As far as I can tell you can pass any any settings that is available in the constructor.
In the Backbone sample (http://handsontable.com/demo/backbone.html), they maybe show what you are searching:
var $container = $("#example1"); $container.handsontable({ data: cars, dataSchema: makeCar, contextMenu: true, columns: [ attr("make"), attr("model"), attr("year") ], colHeaders: ["Make", "Model", "Year"] //minSpareRows: 1 //see notes on the left for `minSpareRows` });
Initially, I tried placing <input>
s into the header <th>
s, but HoT's DOM manipulation is kind of aggressive and they get swiftly removed.
I ended up painting <input>
s above HoT (as direct children of <body>
and replacing header values on change
and blur
events.
I used afterOnCellMouseDown
to create the <input>
s:
new Handsontable(
document.getElementById('example'), {
rowHeaders: true,
colHeaders: true,
minRows: 10,
minCols: 10,
afterOnCellMouseDown: function(event, coords, th) {
if (coords.row === -1 || coords.col === -1) {
let instance = this,
isCol = coords.row === -1,
input = document.createElement('input'),
rect = th.getBoundingClientRect(),
addListeners = (events, headers, index) => {
events.split(' ').forEach(e => {
input.addEventListener(e, () => {
headers[index] = input.value;
instance.updateSettings(isCol ? {
colHeaders: headers
} : {
rowHeaders: headers
});
setTimeout(() => {
if (input.parentNode)
input.parentNode.removeChild(input)
});
})
})
},
appendInput = () => {
input.setAttribute('type', 'text');
input.style.cssText = '' +
'position:absolute;' +
'left:' + rect.left + 'px;' +
'top:' + rect.top + 'px;' +
'width:' + (rect.width - 4) + 'px;' +
'height:' + (rect.height - 4) + 'px;' +
'z-index:1060;';
document.body.appendChild(input);
};
input.value = th.querySelector(
isCol ? '.colHeader' : '.rowHeader'
).innerText;
appendInput();
setTimeout(() => {
input.select();
addListeners('change blur', instance[
isCol ? 'getColHeader' : 'getRowHeader'
](), coords[isCol ? 'col' : 'row']);
});
}
}
}
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/handsontable/5.0.0/handsontable.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/handsontable/5.0.0/handsontable.min.css" rel="stylesheet" />
<div id="example"></div>
Fiddle here.
Note: You don't really need the z-index
if you're in full control of your page's CSS, but I used this in a heavily customized Bootstrap based theme, inside a modal, having z-index:1050
, so I had to give <input>
s more to render them above `.modal-dialog'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With