Handsontable & React
Asked Answered
S

4

8

I'm starting with react and trying to set up handsontable in my react app following: react-handsontable

// import React...
import React from 'react';
import ReactDOM from 'react-dom';

// ... Handsontable with its main dependencies...
import moment from 'moment';
import numbro from 'numbro';
import pikaday from 'pikaday';
import Zeroclipboard from 'zeroclipboard';
import Handsontable from 'handsontable';

// ... and HotTable
import HotTable from 'react-handsontable';

class ExampleComponent extends React.Component {
  constructor(props) {
    super(props);
    this.handsontableData = [
      ["", "Ford", "Volvo", "Toyota", "Honda"],
      ["2016", 10, 11, 12, 13],
      ["2017", 20, 11, 14, 13],
      ["2018", 30, 15, 12, 13]
    ];
  }

  render() {
    return (
      <div id="example-component">
        <HotTable root="hot" data={this.handsontableData} colHeaders={true} rowHeaders={true} width="600" height="300" stretchH="all" />
      </div>
    );
  }
}

Works so far but how do I get the instance of the table like in pure javascript

var ht = new Handsontable(document.getElementById('example1'), options);


ht.setDataAtCell(0, 0, 'new value');

Thanks, Tim

Seesaw answered 7/5, 2017 at 11:54 Comment(0)
F
8

If you're trying to access the core methods, like 'setDataAtCell()', you can use refs to access them.

For example add the "ref='xyz'" attribute to the HTML element and you can then call it with "this.refs.xyz". I've modified your example below to illustrate. It adds a button that onClick runs a function to 'setDataAtCell'.

// import React...
import React from 'react';
import ReactDOM from 'react-dom';

// ... Handsontable with its main dependencies...
import moment from 'moment';
import numbro from 'numbro';
import pikaday from 'pikaday';
import Zeroclipboard from 'zeroclipboard';
import Handsontable from 'handsontable';

// ... and HotTable
import HotTable from 'react-handsontable';

class ExampleComponent extends React.Component {
  constructor(props) {
    super(props);
    this.handsontableData = [
      ["", "Ford", "Volvo", "Toyota", "Honda"],
      ["2016", 10, 11, 12, 13],
      ["2017", 20, 11, 14, 13],
      ["2018", 30, 15, 12, 13]
    ];
  }

  handleClick(e) {
    this.refs.hot.hotInstance.setDataAtCell(0, 0, 'new value')
  }

  render() {
    return (
      <div id="example-component">
        <HotTable root="hot"
                  data={this.handsontableData}
                  colHeaders={true}
                  rowHeaders={true}
                  width="600"
                  height="300"
                  stretchH="all"
                  ref="hot"
        />
        <br/>
        <button onClick={(e)=>this.handleClick(e)}>Click Me</button>
      </div>
    );
  }
}

export default ExampleComponent

This method can be used to access other methods like "getData()" which can be used to get a snapshot of the data in the table which can be saved to state or similar. So it's more lengthy than "ht" you can use "this.refs.hot.hotInstance" for similar affect.

You can read more about the ref attribute in "Refs and the DOM" in the React documentation.

Ferri answered 15/6, 2017 at 19:40 Comment(1)
Thanks, this worked for me, but React now recommends using the createRef API instead of using this.refs directly (more info).Farrica
Q
4

To access the instance of HotTable component, use ref. However, don't use old way of using ref. As of version 16.3, React provides 2 ways :

  • using createRef API which is the recommended way
  • using callback ref which is already available in earlier version, but better than the old "string ref" way.

I only show how to use createRef here :

  1. In your constructor, add the following :

    this.refToHotIns=React.createRef();
    

    The name of the field property is arbitrary, you can name it as you like.

  2. In your render() method, change the JSX element to :

       <HotTable ref={this.refToHotIns} data={this.handsontableData} colHeaders={true} rowHeaders=true} width="600" height="300" stretchH="all" />
    
  3. Now, this.refToHotIns.current references to mounted HotTable instance. The Handsontable instance is stored under the hotInstance property of the wrapper component. So you can then access properties/methods of HotTable instance, like so :

    this.refToHotIns.current.hotInstance.setDataAtCell(0, 0, 'new value');
    
Quirinus answered 24/11, 2018 at 7:35 Comment(0)
E
3

It's pretty simple to write your own react wrapper for handsontable, and then you can create a reference to your HOT instance. Here is some sample React component code:

componentWillReceiveProps({ gridSpec }) {

     if (gridSpec) {
        const {columns, colHeaders, data} = gridSpec;
        const container = document.getElementById(GRID_ID);

        this.hotInstance = new handsontable(container, {
            columns,
            colHeaders,
            data,
            height: 600
        });
    }
}

shouldComponentUpdate () {

    return false;
 }

render () {
    return (
        <div style={{overflowX: 'hidden', height: '600px'}}>
            <div id={GRID_ID} />
        </div>
    )
}
Eyra answered 22/5, 2017 at 22:10 Comment(2)
Thanks, I will try this.Seesaw
Good example but i think it is better to use react ref instead of grid idHinduism
D
1

you have your data as an array defined in the constructor.

this.handsonetableData = [[First row],[second row]]

You could simply link that data to a state and setState inside your component. It should be really straightforward.

this.state = {
  table: [[first line], [second line]]
}

Eventually going further you can write your own method that update a specific value of that array.

constructor (props) {
  super(props)
  this.state = {
    table: [[first row], [second row]]
  }
}
updateValueInTable (row, col, value)
  checkIdontDoAnythingStupid()
  let newTable = this.state.table
  newTable[row][col] = value
  this.setState({ table: newTable})
}

If you do not want to use the state and use something like redux you put the logic in the reducer and the triggers in actions. And there you are!

Of course is up to you how to check that you manipulate correctly your array, a lot of libraries can come to help (lodash and co.)

Densify answered 16/5, 2017 at 3:12 Comment(5)
thanks for your answer, but this sill does not give me an instance of the table.Seesaw
sorry Tim, why do you need an instance of the Table when can control it with the array? I ask to understand better your question..Densify
I need a instance to be able to use the handsontable api not only data manipulation.Seesaw
also when you do things like sorting, the afterchange event gives you the logical indexes, not the physical ones. This means the data you are working with will come out of sync with the data in the state.Yamashita
@Tim, here's how to access the data: handleClick(e) { console.log(this.refs.hot.props.data); }Lucylud

© 2022 - 2024 — McMap. All rights reserved.