How do I edit the header text of a Handsontable?
Asked Answered
P

4

21

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

Piecrust answered 21/8, 2013 at 3:33 Comment(2)
Why are you trying to avoid having them be normal cells? You should be able to use CSS to style them however you like so they appear different from the other cells.Cytherea
@alxndr, yeah it looks like that's the way to do it after all. That said, it would be nice if editing header content was supported.Piecrust
W
25

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.

Wotan answered 2/11, 2014 at 21:36 Comment(3)
I believe this only provides the capacity to do what I was looking to do programatically, as opposed to letting the cell itself be directly editable.Piecrust
Needed this a few days back, so I came up with a function to allow modification of header upon click. I guess it could be improved (enable keyboard navigation to next cell?) but what I needed was only basic, so that's what I coded, thought I'd share.Contributory
so @AndreiGheorghiu, does your solution work? I didn't see where you'd posted the code?Selfpreservation
G
4

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`
});
Glarum answered 21/8, 2013 at 5:20 Comment(1)
Thanks for the answer. I'm actually looking for a way to allow the user to edit the header values (as they would a normal table cell).Piecrust
C
4

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'

Contributory answered 13/7, 2018 at 14:42 Comment(0)
A
0

One way of doing this is to use afterGetColHeader.

Copy pasted from here

afterGetColHeader: function (col, TH) {
    // nothing for first column
    if (col == -1) {
        return;
    }
    var instance = this;
    // create input element
    var input = document.createElement('input');
        input.type = 'text';
        input.value = TH.firstChild.textContent;

    TH.appendChild(input);

    Handsontable.Dom.addEvent(input, 'change', function (e){
        var headers = instance.getColHeader();
            headers[col] = input.value;
        instance.updateSettings({
            colHeaders: headers
        });
    });

    TH.style.position = 'relative';
    TH.firstChild.style.display = 'none';
}
Albumin answered 11/1, 2018 at 9:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.