I'm having trouble adding checkboxes to rows using this react-table package https://react-table.js.org/#/story/readme
I'm trying to add a checkbox to each row in my table. I tried adding "checkbox" to the "Cell" value seen in the columns area, however, it seems that it doesn't work well with the pagination. Once I click next page and then back it forgets all of the previously checked products. How do I maintain their state?
I added a key, and it prevents the element from being checked on all pages, however, it doesn't remember it when I change back and forth on the pages. So I just need to store its "on state" now.
Cell: rowInfo => (<Checkbox key={rowInfo.index} onChange={this.handleChange} />)
Here's the full code:
import React from 'react'
import ReactDOM from 'react-dom'
import ReactTable from 'react-table'
import PropTypes from 'prop-types'
import { Checkbox } from '@shopify/polaris';
export default class ProductIndexTable extends React.Component {
constructor(props) {
super(props);
this.state = {
rowInfo: ''
}
this.handleChange = this.handleChange.bind(this)
}
handleChange(event) {
}
render() {
function CreateItem(product) {
return {
title: <a href={'/products/' + product.id} >{product.title}</a>,
price_test_status: product.has_active_price_test,
price_test_completion_percentage: product.price_test_completion_percentage
}
}
return (<ReactTable
data={this.props.products.map(CreateItem)}
getTdProps={(state, rowInfo, column, instance) => {
return {
onClick: (e, handleOriginal) => {
// console.log('A Td Element was clicked!')
// console.log('it produced this event:', e)
// console.log('It was in this column:', column)
// console.log('It was in this row:', rowInfo)
// console.log('It was in this table instance:', instance)
this.setState({
rowInfo: rowInfo.index
})
// IMPORTANT! React-Table uses onClick internally to trigger
// events like expanding SubComponents and pivots.
// By default a custom 'onClick' handler will override this functionality.
// If you want to fire the original onClick handler, call the
// 'handleOriginal' function.
if (handleOriginal) {
handleOriginal()
}
}
}
}}
columns={[
{
Header: "Base",
columns: [
{
Header: <Checkbox />,
maxWidth: 50,
Cell: (<Checkbox onChange={this.handleChange} />)
}, {
Header: "Product Title",
accessor: "title",
maxWidth: 400
}, {
Header: "Price Test Status",
accessor: "price_test_status",
maxWidth: 200
}, {
Header: "Price Test Completion Percentage",
accessor: "price_test_completion_percentage",
Cell: row => (
<div
style={{
width: '100%',
height: '100%',
backgroundColor: '#dadada',
borderRadius: '2px'
}}
>
<div
style={{
width: `${row.value}%`,
height: '100%',
backgroundColor: row.value > 66 ? '#85cc00'
: row.value > 33 ? '#ffbf00'
: '#ff2e00',
borderRadius: '2px',
transition: 'all .2s ease-out'
}}
/>
</div>
)
}
]
}
]}
defaultPageSize={10}
className="-striped -highlight"
/>
);}
}
I ended up storing the titles into a hash when clicked and that gave me my final solution. It checks the hash state to see if the value is true and should remain checked. See code below. Hope it helps others! Also check the codepen example I used to help me.
https://codepen.io/aaronschwartz/pen/WOOPRw?editors=0010
import React from 'react'
import ReactDOM from 'react-dom'
import ReactTable from 'react-table'
import PropTypes from 'prop-types'
import { Checkbox } from '@shopify/polaris';
export default class ProductIndexTable extends React.Component {
constructor(props) {
super(props);
this.state = {
selected: {},
selectAll: 0,
products: this.props.products
}
this.toggleRow = this.toggleRow.bind(this);
}
toggleRow(title) {
const newSelected = Object.assign({}, this.state.selected);
newSelected[title] = !this.state.selected[title];
this.setState({
selected: newSelected,
selectAll: 2
});
}
toggleSelectAll() {
let newSelected = {};
if (this.state.selectAll === 0) {
this.state.products.forEach(x => {
newSelected[x.title] = true;
});
}
this.setState({
selected: newSelected,
selectAll: this.state.selectAll === 0 ? 1 : 0
});
}
render() {
function CreateItem(product) {
return {
title: <a href={'/products/' + product.id} >{product.title}</a>,
price_test_status: product.has_active_price_test,
price_test_completion_percentage: product.price_test_completion_percentage
}
}
return (<ReactTable
data={this.props.products.map(CreateItem)}
columns={[
{
Header: "Base",
columns: [
{
id: "checkbox",
accessor: "",
Cell: ( rowInfo ) => {
return (
<Checkbox
type="checkbox"
className="checkbox"
checked={this.state.selected[rowInfo.original.title.props.children] === true}
onChange={() => this.toggleRow(rowInfo.original.title.props.children)}
/>
);
},
Header: title => {
return (
<Checkbox
type="checkbox"
className="checkbox"
checked={this.state.selectAll === 1}
ref={input => {
if (input) {
input.indeterminate = this.state.selectAll === 2;
}
}}
onChange={() => this.toggleSelectAll()}
/>
);
},
sortable: false,
width: 45
},
{
Header: "Product Title",
accessor: "title",
maxWidth: 400
}, {
Header: "Price Test Status",
accessor: "price_test_status",
maxWidth: 200
}, {
Header: "Price Test Completion Percentage",
accessor: "price_test_completion_percentage",
Cell: row => (
<div
style={{
width: '100%',
height: '100%',
backgroundColor: '#dadada',
borderRadius: '2px'
}}
>
<div
style={{
width: `${row.value}%`,
height: '100%',
backgroundColor: row.value > 66 ? '#85cc00'
: row.value > 33 ? '#ffbf00'
: '#ff2e00',
borderRadius: '2px',
transition: 'all .2s ease-out'
}}
/>
</div>
)
}
]
}
]}
defaultPageSize={10}
className="-striped -highlight"
/>
);}
}
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