1

This is an example table data:

const tableData = [
    ['one', 'two', 'three'],
    ['uno', 'dos', 'tres'],
    ['ichi', 'ni', 'san']
]

The data will be rendered like this:

render() {
    <Table>
        <Table.Body>
            {
                tableData.map((row, rowIndex) => {
                    return (
                        <Table.Row key={ rowIndex }>
                            {
                                row.map((cell, cellIndex) => {
                                    return (
                                        <Table.Cell key={ cellIndex }>
                                            <Input
                                                defaultValue={ cell }
                                                onChange={ this.tableChange }
                                            />
                                        </Table.Cell>
                                    )
                                })
                            }
                        </Table.Row>
                    )
                })
            }
        </Table.Body>
    </Table>
}

Now I need to get an updated dataset on onChange of an Input element.

tableChange(event) {
    console.log(event.target.value)
}

This is how I get the updated current element value. But I need to get the complete updated array - like the input array.

I would think of using the key values, but maybe I need some data-attributes?

3
  • Do you have control over the Input component? or is it a library? Commented Jul 6, 2017 at 19:09
  • I have complete control. I can change everything Commented Jul 6, 2017 at 19:11
  • then in the Input component you can add a prop like index that the actual position of the value, <Input defaultValue={ cell } onChange={ this.tableChange } index={cellIndex} /> and return it in your input click handler Commented Jul 6, 2017 at 19:15

1 Answer 1

1

This is just an example to cover your case, so let say we have the Table component which will just render all the code above

Table

class Table extends React.Component {
  constructor() {
    super();

    this.onChange = this.onChange.bind(this);
    this.state = {
      tableData: [
        ['one', 'two', 'three'],
        ['uno', 'dos', 'tres'],
        ['ichi', 'ni', 'san']
      ]
    };
  }

  renderRows() {
    const { tableData } = this.state;

    return tableData.map((cells, rowIndex) => (
      <tr key={ rowIndex }>
        {this.renderCells(cells, rowIndex)}
      </tr>
    ));
  }

  renderCells(cells, rowIndex) {
    return cells.map((cell, cellIndex) => (
      <td key={ cellIndex }>
        <Input
          cellIndex={cellIndex}
          rowIndex={rowIndex}
          defaultValue={cell}
          onChange={this.onChange}
        />
      </td>
    ));
  }

  onChange(event, cellIndex, rowIndex) {
    this.state.tableData[rowIndex][cellIndex] = event.target.value;
    const tableData = this.state.tableData;

    console.log('values:', event.target.value, cellIndex, rowIndex);
    console.log('tableData:', tableData);

    this.setState({ tableData });
  }

  render() {
    return (
      <table>
        <tbody>
          {this.renderRows()}
        </tbody>
      </table>
    );
  }
}

Input

function Input({ onChange, cellIndex, rowIndex, defaultValue }) {
  const onInputChange = event => {
    onChange(event, cellIndex, rowIndex);
  };

  return (
    <input
      type="text"
      value={defaultValue}
      onChange={onInputChange}
    />
  );
}

There is nothing wrong with passing the index of the elements.
As you can see in the <Input /> component you can pass the reference of rowIndex and cellIndex so you the component knows which element of the array is being updated and then notify it to the parent when the onChange event is triggered.

Here is a working example of this, check it out: https://codepen.io/anon/pen/awjgKb?editors=0010

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.