DJ2
DJ2

Reputation: 1741

React - move row of data to new table based on checkbox

I have a table of schedules that is populated by a series of api calls. I'm using SUIR to render each schedule and some identifying information in a <Table>. I added a slider in an unmarked column before each schedule. This will represent the boolean option to "export" the schedule.

  <Table.Body>
    {Object.values(schedules).map(
      ({ id, startTime, selfUri, status }) => {
        return (
          <Table.Row>
            <Checkbox slider onChange={this.slider} />
            <Table.Cell>{id}</Table.Cell>
            <Table.Cell>
              {format(startTime, "MMM Do YYYY, h:mm:ss A")}
            </Table.Cell>
            <Table.Cell>{selfUri}</Table.Cell>
            <Table.Cell>{status}</Table.Cell>
          </Table.Row>
        );
      }
    )}
  </Table.Body>

I currently have this slider change handler

  slider = () =>
    this.setState({ exportSlider: !this.state.exportSlider }, () => {
      console.log("slider --> ", this.state.exportSlider);
    });

But this only keeps track of one slider state. How can I keep track of each slider state from each corresponding schedule? And how can I take the slider === true schedules and add them to a new table to be exported?

I have a code sandbox here that has a few schedules and the slider functionality.

Upvotes: 1

Views: 1769

Answers (1)

etarhan
etarhan

Reputation: 4176

You could abstract your table row into a separate component. Then you can have every row track it's own slider state. Example of a component like this could be the following:

import React, { Component } from "react";
import { Table, Checkbox } from "semantic-ui-react";
import format from "date-fns/format";

export default class TableRowWithSlider extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      exportSlider: false
    };
  }
  slider = () => {
    this.setState({ exportSlider: !this.state.exportSlider }, () => {
      console.log("slider --> ", this.state.exportSlider);
      const { id, slide } = this.props;
      slide({ id, isExported: this.state.exportSlider });
    });
  };

  render() {
    const { id, startTime, selfUri, status } = this.props;
    return (
      <React.Fragment>
        <Table.Row>
          <Checkbox slider onChange={this.slider} />
          <Table.Cell>{id}</Table.Cell>
          <Table.Cell>{format(startTime, "MMM Do YYYY, h:mm:ss A")}</Table.Cell>
          <Table.Cell>{selfUri}</Table.Cell>
          <Table.Cell>{status}</Table.Cell>
        </Table.Row>
      </React.Fragment>
    );
  }
}

Check out the sandbox for the full solution: click. The parent component is keeping the state stored of all the schedule ids that should be exported. The child component AKA TableRowWithSlider calls it's own slide handler as well as the parent's slide handler to pass it's id and toggle state.

The table body looks like this:

<Table.Body>
  {Object.values(schedules).map(
    ({ id, startTime, selfUri, status }) => {
      return (
        <TableRowWithSlider
          id={id}
          startTime={startTime}
          selfUri={selfUri}
          status={status}
          slide={this.slider.bind(this)}
        />
      );
    }
  )}
</Table.Body>

And the parent's slide handler looks like this:

slider = ({ id, isExported }) => {
  if (isExported === true) {
    this.setState(
      {
        scheduleIdsToExport: [id, ...this.state.scheduleIdsToExport]
      },
      () => console.log(this.state.scheduleIdsToExport)
    );
  } else {
    const newArray = this.state.scheduleIdsToExport.filter(
      storedId => storedId !== id
    );
    this.setState(
      {
        scheduleIdsToExport: newArray
      },
      () => console.log(this.state.scheduleIdsToExport)
    );
  }
};

Check full solution here

Upvotes: 1

Related Questions