Skip to content
This repository has been archived by the owner on Jan 13, 2022. It is now read-only.

Table not scrollable on Mobile #365

Open
CoderBlaine opened this issue Mar 9, 2016 · 7 comments
Open

Table not scrollable on Mobile #365

CoderBlaine opened this issue Mar 9, 2016 · 7 comments

Comments

@CoderBlaine
Copy link

I've created a simple table and it displays fine on pc however when viewing it on mobile it does not scroll.

However the examples seem to scroll any idea what would cause this?

@CoderBlaine
Copy link
Author

Here is an example that will not scroll in mobile.

http://pastebin.com/TjgV2ebv

@vinayaknagpal
Copy link

I ran into this a few weeks ago. Turns out touch events need to be explicitly captured and handled to get scrolling on mobile devices.

The site examples offer a good starting point, check out this commit

@ssolders
Copy link

ssolders commented Apr 15, 2016

I'm having this issue as well, has anyone come up with a good solution?
Can you give any further directions @vinayaknagpal ?

@CoderBlaine
Copy link
Author

Hi,

Scrolling for mobile is not automatically built in. So you need to go through the steps of adding the mobile scroll wrapper as per the commit example posted by vinayaknagal above.

Hopefully they build this feature in to a future version as I imagine almost everyone wants support for mobile.

@ssolders
Copy link

ssolders commented Apr 19, 2016

Hi,
Yea I realize that, I guess I was looking for some more extensive examples.
I've managed to get it "working", but having the issue that when I stop scrolling in the table it resets to its initial position (resets to left: 0, top: 0).

It's reset using the _handleScroll function, not due to the component "reseting" and setting the initial state.

I've updated TouchWrapper/TouchableArea to use ES6 class + export so I can use import instead of require, that's the only updates to those files.

Here are my relevant files:
https://plnkr.co/edit/S7doxrrMb0mjnl4aYATA

Any ideas?

Edit: I worked out the reset problem by not calling this.props.scroller.doTouchEnd(e.timeStamp) in the handleTouchEnd in TouchableArea.js along with only setting a new top + left value in state if they are > 0.

  handleTouchEnd(e) {
    if (!this.props.scroller || !this.props.touchable) {
      return;
    }
    //Without this the scroller was reset to top:0 left: 0 on touchEnd.
    e.preventDefault();
    return
    // this.props.scroller.doTouchEnd(e.timeStamp);
  } 
    _handleScroll(left, top) {
        //Don't allow to scroll sub 0
        this.setState({
            left: ( left > 0  ? left : 0),
            top: ( top > 0  ? top : 0)
        });
    }

@alexandergunnarson
Copy link

alexandergunnarson commented Apr 26, 2016

I've tried the Zynga Scroller as per the TouchWrapper/TouchableArea example, with the helpful hints provided by @ssolders and @vinayaknagpal . However, because Zynga Scroller simply sets props.scrollLeft and props.scrollTop, which according to #202 has no effect after mount. Due to #202, I've been forced to use an older version of FixedDataTable (the July 22nd version of the branch featured in #216 's pull request), which is inconvenient. I'm not even sure whether it works yet, but I'll post back once I try.

I second @CoderBlaine in advocating that Facebook "build[s] this feature in to a future version as I imagine almost everyone wants support for mobile."

UPDATE:
The programmatic scrolling works on desktop! However, the FixedDataTable version in #216 is sadly sufficiently behind the current master branch as to have a different render/data model: it lacks the Cell component and needs props.rowGetter to work. Still trying to work out the kinks in that. But at least it scrolls!

UPDATE 2:
The scrolling is very slow... I think I'm going to make @u9520107's changes to the current version and see what happens. I wish Facebook would enable mobile scrolling by default. Oh well.

UPDATE 3:
I made the changes and scrolling turned out to be painfully slow. Guess FixedDataTable performance has had that great of an improvement in the past few months. I moved to react-canvas and now it scrolls smooth as butter.

@dcoales
Copy link

dcoales commented May 30, 2016

I'm not familiar with Zynga, TouchWrapper etc but I used the following code. I'm new to this so there is probably an easier way but this seems to work. One thing I noticed was that I had to turn off the scroll bars temporarily when on the desktop for the scrollTop and scrollLeft functions to work after the first render. I've got them permanently turned off on mobile.

`
render(){
var Table = FixedDataTable.Table;
return (
<div style={style}
ref={ref=>{this.container=ref}}
onTouchStart={e=>this.__onTouchStart(e)}
onTouchEnd={e=>this.__onTouchEnd(e)}
onTouchMove={e=>this.__onTouchMove(e)}
>
<Table
ref={ref=>this.grid=ref}
{...tableProps}
rowClassNameGetter={rowClassNameGetter}
rowStyleGetter={index => this.__rowStyleGetter(index)}
width={width}
height={height}
onRowDoubleClick={onRowDoubleClick}
onRowClick={onRowClick}
onColumnResizeEndCallback={this.__onColumnResizeEndCallback}
isColumnResizing={false}
onRowMouseEnter={(e, index) => this.__onRowMouseEnter(e, index)}
onRowMouseLeave={(e, index) => this.__onRowMouseLeave(e, index)}
onScrollEnd={(x,y)=>this.__onScrollEnd(x,y)}
scrollTop={this.state.scrollTop}
scrollLeft={this.state.scrollLeft}
overflowX={this.state.overflowX}
overflowY={this.state.overflowY}
>
{columns}


);
}

__onScrollEnd(x,y){
    // remember the scroll position at the end of mouse or wheel scrolling
    if (!this.touching){
        this.state.scrollLeft = x;
        this.state.scrollTop = y;
    }
}

__onTouchStart(e){
    if (!this.mobile)this.setState({overflowX:'hidden',overflowY:'hidden'});
    this.touching = true;
    this.touchStart = this.__getTouchCoordinates(e);
}
__onTouchMove(e){
    e.preventDefault();
   this.__scrollGrid(e)
}
__onTouchEnd(e){
    this.touching = false;
    if (!this.mobile)this.setState({overflowX:'auto',overflowY:'auto'});
}

__scrollGrid(e){
    var touchEnd = this.__getTouchCoordinates(e);
    var scrollX = touchEnd.x - this.touchStart.x ;
    var scrollY = touchEnd.y - this.touchStart.y;

    var deltaX = scrollX < 0 ? scrollX * -1 : scrollX;
    var deltaY = scrollY < 0 ? scrollY * -1: scrollY;

    var scrollLeft, scrollTop;
    if (deltaX > deltaY){
        scrollLeft = Math.max(0,this.state.scrollLeft - scrollX);
        scrollTop = this.state.scrollTop;
    } else {
        scrollLeft = this.state.scrollLeft;
        scrollTop = Math.max(this.state.scrollTop - scrollY);
    }

    this.setState({scrollLeft: scrollLeft, scrollTop: scrollTop});
    this.touchStart = touchEnd;
}

__getTouchCoordinates(e){
    var touches = e.nativeEvent.changedTouches;
    if (touches && touches.length > 0){
        return {x:touches.item(0).clientX, y: touches.item(0).clientY};
    }
    return false;
}

`

Any suggestions for improvements gratefully received :-)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants
@CoderBlaine @alexandergunnarson @vinayaknagpal @ssolders @dcoales and others