16

I am using react-table in my application.

I am stuck in doing one thing i.e. changing the CSS of columns while a column is being resized.

Currently when you resize a column only cursor changes. What I want is to add border to the selected column.

I searched for this on SO and google as well. But couldn't find anything useful. And In the documentation as well nothing is mentioned about this topic as well.

Update

Now I am able to add border while dragging the column while resizing. I am able to do so by adding and removing the class.

What I did to do so:

Created a var in the state for className:

  this.state = {
         addBorder: null
   }

Passed this class name in my column:

     const columns = [{
    Header: 'Name',
    accessor: 'name', // String-based value accessors!,
    headerClassName: this.state.addBorder,
    className: this.state.addBorder
}, {
    Header: 'Age',
    accessor: 'age',
    Cell: props => <span className='number'>{2}</span> // Custom cell components!
}, {
    id: 'friendName', // Required because our accessor is not a string
    Header: 'Friend Name',
    accessor: d => d.friend.name // Custom value accessors!
}, {
    Header: props => <span>Friend Age</span>, // Custom header components!
    accessor: 'friend.age'
}];

return (
    <div onMouseUp={this.handleMouseUp}>
    <ReactTable
        data={data}
        columns={columns} 
        resizable={true}
        onResizedChange={(col, e) => {
            const column = col[col.length-1];
            this.setState({addBorder: column.id})
        }} />
        </div>
)
}

To remove the class when dragging ends:

   handleMouseUp (e) {
    this.setState({addBorder: null});
}

But I am still not able to add border on hover.

Now, I am sending my custom HTML in header props. And in my HTML I have made an extra div. And I have moved this div to right. And on hover of this div, I am emitting mouse events and changing CSS accordingly.

But Existing div in the header that is responsible for resizing column is overlapping with my Div.

  Header: props => <div className='header-div'> Name <div onMouseOver = {() => {
        console.log('mose');
        this.setState({className: 'addBorder'});
    }} className='hover-div' onMouseOut = {() => {console.log('sdasd');this.setState({className: null});}}> </div></div> ,
1
  • I don't think there is a handler to do this. However you could make up a hack with onResizedChange callback. Commented Feb 16, 2018 at 8:11

3 Answers 3

6
+50

From what I understand, you want to add some border when you hover over a column header. If my understanding is correct, you can use :hover pseudo selector over the header class

.hdrCls:hover {
  border: 2px solid rgba(0,0,0,0.6) !important;
}

Update :

You can manipulate state in onResizedChange handler exposed by react-table

onResizedChange={(newResized, event) => {
  let resizedCol = newResized.slice(-1)[0].id;
  if(this.state.activeCol !== resizedCol) {
    this.setState({
      activeCol: resizedCol,
      resizing: true
    })
  }
}}

Also, make sure you have to make the resizing state to false on mouseup event. For that I have come up with the below solution.

componentDidUpdate(props, state) {
  if (this.state.resizing && !state.resizing) {
    document.addEventListener('mouseup', this.onMouseUp);
  } else if (!this.state.resizing && state.resizing) {
    document.removeEventListener('mouseup', this.onMouseUp);
  }
}

onMouseUp = (evt) => {
  this.setState({
    activeCol: '',
    resizing: false
  });
  evt.stopPropagation();
  evt.preventDefault();
}      

For reference:

const ReactTable = window.ReactTable.default

class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      activeCol: '',
      resizing: false
    }
  }
  
  componentDidUpdate(props, state) {
    if (this.state.resizing && !state.resizing) {
      document.addEventListener('mouseup', this.onMouseUp);
    } else if (!this.state.resizing && state.resizing) {
      document.removeEventListener('mouseup', this.onMouseUp);
    }
  }
  
  onMouseUp = (evt) => {
    this.setState({
      activeCol: '',
      resizing: false
    });
    evt.stopPropagation();
    evt.preventDefault();
  }
  
  render() {
    const data = [{
      name:"Mark",
      age:24
    },
    {
      name:"Derek",
      age:26
    }]

    const columns = [{
          Header: 'Name',
          accessor: 'name', // String-based value accessors!,
          headerClassName: 'hdrCls',
          className: (this.state.activeCol === 'name') && this.state.resizing ? 'borderCellCls' : 'defaultCellCls'
      }, {
          Header: 'Age',
          accessor: 'age',
          headerClassName: 'hdrCls',
          className: (this.state.activeCol === 'age') && this.state.resizing ? 'borderCellCls' : 'defaultCellCls'
      }];

    return <ReactTable
      data = { data }
      columns = { columns }
      showPagination= {false}
      onResizedChange={(newResized, event) => {
        let resizedCol = newResized.slice(-1)[0].id;
        if(this.state.activeCol !== resizedCol) {
          this.setState({
            activeCol: resizedCol,
            resizing: true
          })
        }
      }}
    />
  }
}

ReactDOM.render( < App / > , document.getElementById("app"))
.hdrCls:hover {
  border: 2px solid rgba(0,0,0,0.6) !important;
}


.borderCellCls {
  border-right: 2px solid rgba(0,0,0,0.6) !important;
  border-left: 2px solid rgba(0,0,0,0.6) !important;
}

.defaultCellCls {
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-table/6.7.6/react-table.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/react-table/6.7.6/react-table.css"></link>
<div id="app"></div>

You can play around with CSS. Hope this is what you want and hope this helps.

Update:

I think you have to play with CSS to achieve what you desire.

.borderCellCls {
   border-right: 2px solid rgba(0,0,0,0.6) !important;
   border-left: 2px solid rgba(0,0,0,0.6) !important;
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks @dev, In your solution only one column is highlighting when I hover the edge of the column. What I want is to add border in while column rather than adding on one cell.
@Dalvik, yes according to the above logic, when you try to resize a particular column, that column would get border. This was my understanding. Correct me if I am wrong, what you want is the same behavior but instead of cells getting highlighted whole column should show border during resizing. Right ??
@Dalvik, I think if the above answer is close to what you want, and the only problem being, the border should be shown to the column instead of cell, I would suggest you can manipulate this with CSS to achieve the desired result. But happy to help. I will try again once I get time.
4

If you are here to find out how to set className to a column cell (with the react-table), here is the solution:

1)

<tr
            
              {...row.getRowProps()}
            >
              {row.cells.map((cell) => (
                <td
                  {...cell.getCellProps([
                    {
                      className: cell.column.className, // pay attention to this
                      style: cell.column.style,
                      // set here your other custom props
                    },
                  ])}
                >
                  {cell.render('Cell')}
                </td>
              ))}
            </tr>

2)

  const columns = React.useMemo(
() => [
  {
    Header: 'Date',
    accessor: 'date',
    minWidth: 70,
    className: 'text-dark fw-bolder fs-6 min-w-70px', // pass className props here
    headerClassName: 'text-muted', // or another props like this one
  }]
  
<Table columns={columns} ... />

And finally, those props will be passed to your cells

1 Comment

'className' maps to the attribute that React uses to specify CSS class on DOM elements - reactjs.org/docs/dom-elements.html
1

For TypeScript support follow the instructions in DefinitelyTyped, ie. create the file /src/types/react-table-config.d.ts with the content from the instructions, then add the following to it to support custom properties on your column (add more properties in the last line as required):

  // Added to support classes to template from:
  // https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react-table
  export interface ColumnInstance<
    D extends Record<string, unknown> = Record<string, unknown>
  > extends Omit<ColumnInterface<D>, 'id'>,
      ColumnInterfaceBasedOnValue<D>,
      UseTableColumnProps<D>,
      Record<headerClassName | className, string> {}

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.