Is there a preferred way to make a row selectable? As in when the user clicks on any cell in a row that row is marked/highlighted? I'm trying to do this through custom properties and cell renderers but that seems to be a non-optimal workaround.
Cheers,
Martin
I built a select column with a checkbox in it. This avoids fighting with subcomponents and custom cell renderers. I set getTdProps on the ReactTable like so:
getTdProps={(state, rowInfo, column, instance) => {
return {
className: (this.isSelected(rowInfo))? "SelectedRow" : ""
}
}}
Then I add a column with the checkbox this:
columns.push({
Header: "Select",
accessor: "id",
Cell: row => (
<input type="checkbox"
onClick={(e) => {
if (this.isSelected(row)) {
this.deselectRow(row)
} else {
this.selectRow(row)
}
}}
checked={this.isSelected(row)}
/>
)
})
Row selection is just a few simple functions to manage a state object telling which rows are selected for use elsewhere.
Since this is more of an implementation question and not an issue or bug,
we suggest you use our slack channel to ask for more assistance. Thanks!
@corymainwaring hey man I am also doing a similar feature that is involving checkboxes, have you managed to fix your problem? I would like to know how you did it
Yeah I actually figured out how to do this. I didn't need a checkbox though. All I was looking for was a way to visually show which row the user had clicked on/selected. So in my case a simple bold font for the selected row was sufficient. I've distilled the relevant code from an existing class below for a component that has a table with the selection feature. I haven't tried to compile and run this code but it should be very close to a cut and paste example.
The main idea is that you add an extra hidden variable that tracks if a row is selected. You then
use that to set a selected row variable in the state of the component that uses the table.
import React from 'react';
import ReactTable from 'react-table'
import 'react-table/react-table.css'
export default class PipelineSelector extends React.Component {
constructor (props) {
super(props);
this.state = {
pipelines: [],
selectedIndex: -1
};
this.pipelineTable = [{
Header: 'Name',
accessor: 'name',
Cell: (row) => this.renderCell (row)
}, {
Header: 'Description',
accessor: 'description',
Cell: (row) => this.renderCell (row)
}, {
Header: 'Created',
accessor: 'created',
Cell: (row) => this.renderCell (row)
}, {
Header: 'Modified',
accessor: 'modified',
Cell: (row) => this.renderCell (row)
}];
this.selectPipeline = this.selectPipeline.bind(this);
}
renderCell (row) {
if (row.original.selected==true) {
return (<div style={{cursor: "default", fontWeight: "bold"}}>{row.value}</div>);
}
return (<div style={{cursor: "default", fontWeight: "normal"}}>{row.value}</div>);
}
componentWillReceiveProps(nextProps) {
var annotated=this.annotatePipeline (nextProps.pipelines);
this.setState ({pipelines: annotated});
}
// Assume that any data we're getting doesn't have our hidden 'selected' feature. So
// here we add it manually
annotatePipeline (pipelineList) {
var annotated=new Array ();
for (var i=0;i < pipelineList.length;i++) {
var converter=pipelineList [i];
converter ["selected"]=false;
annotated.push (converter);
}
return (annotated);
}
/**
*
*/
selectPipeline (e,state,column,rowInfo,instance) {
if (this.state.selectedIndex!=-1) {
var pipelineOld=this.state.pipelines [this.state.selectedIndex];
pipelineOld.selected=false;
}
var pipeline=this.state.pipelines [rowInfo.index];
pipeline.selected=true;
if (pipeline!=null) {
if (this.props.onClickPipeline) {
this.props.onClickPipeline (pipeline.name);
} else {
console.log ("No event handler available to process pipeline select event");
}
} else {
console.log ("Error retrieving pipeline from pipeline list");
}
this.setState ({selectedIndex: rowInfo.index});
}
/**
*
*/
render() {
let pipelines=<ReactTable data={this.state.pipelines}
columns={this.pipelineTable}
showPagination={false}
className='-striped -highlight'
defaultPageSize={10}
getTdProps={(state, rowInfo, column, instance) => {
return {
onClick: e => { this.selectPipeline (e,state,column,rowInfo,instance) }
}
}
}/>;
return (
<div>
{pipelines}
</div>);
}
}
@xxryan1234 What @Mindtoeye posted is the most straightforward way of implementing a "selected" row. That way broke subcomponents for me (can't open them, because the onClick for td props is overriding the subcomponent expander). However, what I outlined above is how I got subcomponents and selecting rows to work. You keep the selection state updated outside of the table and have the table ask about it in getTdProps and just update it's visual style, rather than letting the table do the click actions.
I haven't found a way to use getTdProps to do row selection without breaking subcomponents.
@corymainwaring found in documentation how to solve this issue,
getTdProps={(state, rowInfo, column, instance) => {
return {
onClick: (e, handleOriginal) => {
//here should be code for selection
if (handleOriginal) {
handleOriginal()
}
}