4

I have an outer parent <div /> container that contains a <Table /> element. I'd like to be able to scroll the <Table /> on the onWheel event of the parent <div /> element, even if the mouse is not currently over the <Table />.

I have a ref to the table element and an event handler listening for the onWheel event but I haven't been able to figure out how to forward that event down to the table.

arb
  • 7,753
  • 7
  • 31
  • 66
  • Can you show us what you've tried so far? – T Porter Dec 14 '17 at 16:24
  • maybe use the .scrollTo function to trigger a scroll on the table but you'll have to do some calculations – monssef Dec 14 '17 at 16:28
  • @monssef yeah that was a thought I had... I'd like to avoid that if possible though. Partially because it seems unnecessarily complicated and partially because I have no idea what the calculation would look like. – arb Dec 14 '17 at 16:45

2 Answers2

1

I made a codePen illustrating a scroll redirection

This will listen wheelEvent on a parent <div>(the one with a red background), disable the default scrolling behavior (evt.preventDefault()) then set the scrollTop position of another <div>.

Here's the component code :

class RedirectScroll extends React.Component {
    parentOnScroll = (evt) => {
        evt.preventDefault();
        const scrollTo= (evt.deltaY) + this.box.scrollTop;
        this.box.scrollTop = scrollTo;
    }
    render() {
        return (
            <div className="parent" onWheel={this.parentOnScroll}> // Listen scrolls on this div
               <div className="scrollablebox" ref={(box) => this.box = box}>
                   // Some content
               </div>
            </div>
        );
    }
}

I hope this is what you're looking for.

Dyo
  • 4,429
  • 1
  • 15
  • 30
  • This has the react-virtualized tag, I'd expect the answers to leverage the built-in API, rather than drop down to DOM methods. – arb Dec 30 '17 at 23:12
1

Because I guess that you want to scroll the table body, you can try with this.

class Table extends React.Component {

    constructor() {
        super();
        this.callback = this.callback.bind(this);
        this.body = null;
    }

    callback(ev) {
        
        this.body.scrollTop += ev.deltaY;
    }
    
    render() {
        return <div onWheel={this.callback}>
            <table>
                <tbody ref={c => this.body = c}>
                    {[1, 2, 3, 4, 5, 6,].map(i => <tr>
                        <td>{i}</td>
                    </tr>)}
                </tbody>
            </table>
        </div>;
    }
}

ReactDOM.render(<Table />, document.getElementById('root'));
tbody {
  display: block;
  height: 3rem;
  overflow: scroll;
}

tr:nth-child(2n+1) {
  background-color: #ddf;
}

tr:nth-child(2n) {
  background-color: #eef;
}

table {
  margin: auto;
  border-collapse: collapse;
}

td {
  width: 5rem;
  text-align: center;
  font-family: sans-serif;
  color: #00f;
}

div {
  width: 100%;
  display: block;
  text-align: center;
  background-color: #99f;
}
<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>
<div id="root"></div>
dlopez
  • 969
  • 5
  • 17
  • This has the react-virtualized tag, I'd expect the answers to leverage the built-in API, rather than drop down to DOM methods. – arb Dec 30 '17 at 23:12