Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sticky headers #780

Closed
KATT opened this issue Jul 2, 2019 · 16 comments
Closed

Sticky headers #780

KATT opened this issue Jul 2, 2019 · 16 comments
Labels
feature help wanted Extra attention is needed wontfix This will not be worked on

Comments

@KATT
Copy link
Contributor

KATT commented Jul 2, 2019

Is your feature request related to a problem? Please describe.
Yes.

Describe the solution you'd like
Headers to be sticky.

Describe alternatives you've considered
Finding a way to override styles

Additional context

Seems like the <ScrollBar/>-component which adds a wrapper with overflow, makes it impossible.

Not sure why #709 was closed.

@karrettgelley
Copy link

The reason I closed it is because there is a very easy solution that I found. First you need to set the header style to sticky:

options={{ headerStyle: { position: 'sticky', top: 0 } }}

This alone does not do anything. Next you need to set the body height of the table in order to trigger a vertical scrollbar to appear:

options={{ headerStyle: { position: 'sticky', top: 0 }, maxBodyHeight: '650px' }}

The combination of these two function will allow you to have sticky table headers. Hope this helps. Perhaps it should be added to the docs if this is an acceptable solution

@ingvaldlorentzen
Copy link
Contributor

Is there any way to do this without setting the maxBodyHeight ?

I have a table (without pagination) in a view, where I want a sticky header.
But when setting maxBodyHeight this creates a new scrollbar within the table. I want the main scrollbar to do the scrolling.

Is this possible at the moment? Any tips?

@simromm
Copy link

simromm commented Oct 17, 2019

@karrettgelley
Any tip to stick also the filter row (depending of the height of the header row)?
The dividers (on top and bottom of the filter row) seem to no be impact by the 'sticky' option..

@ryanintulsa
Copy link

ryanintulsa commented Oct 23, 2019

@simromm
Any tip to stick also the filter row (depending of the height of the header row)?
The dividers (on top and bottom of the filter row) seem to no be impact by the 'sticky' option..

I've looked into this and it seems impossible with this project's architecture. The filter row is in the table body rather than the header. I need this for my current project, so my plan is to build a custom header where each cell is a div with the label and a filter.

@ryanintulsa
Copy link

I got sticky filter row to work, but I had to fork the project to do it.

*** WARNING: UGLY HACK AHEAD ***

The key was that col.title doesn't have to be a string. Map this for each column:

addFilterToCol(col) {
    if ('string' !== typeof col.title) return;
    const table = this.table; // This is a MaterialTable ref
    const HeaderCell = () =>
        <TextField
            type='search'
            defaultValue={col.tableData.filterValue || ''}
            placeholder={col.filterPlaceholder || ''}
            style={col.filterCellStyle}
            onClick={(event) => event.stopPropagation()}
            onChange={(event) => {
                const callback = _.get(table.current, 'onFilterChange');
                if (callback) callback(col.tableData.id, event.target.value);
            }}
        />;
    HeaderCell.bind(this);
    Object.assign(col, { textTitle: col.title, title: <>{col.title}<br/><HeaderCell/></> });
}

Note that textTitle was so that in my material-table fork I could display col.textTitle || col.title in the show/hide columns menu. You can leave that out, but you will get filter TextFields in the show/hide columns menu because it uses the now hijacked column title.

Use at your own risk! This is unintended, unsupported functionality!

@ingvaldlorentzen
Copy link
Contributor

Use at your own risk! This is unintended, unsupported functionality!

Would you be willing to make this a bit less of an "ugly hack" and make a pull request out of it?

I think I and a lot of others would love this kind of feature

@ryanintulsa
Copy link

ryanintulsa commented Oct 28, 2019

Would you be willing to make this a bit less of an "ugly hack" and make a pull request out of it?

I think I and a lot of others would love this kind of feature

I hear you. The trouble is to fix this the "right" way would be an architecture-level change for the project, so we would need @mbrn to weigh in. I looked first at just moving the filter row to the header, but that is very difficult as well because making two separate header rows sticky is very difficult in general. It needs to be one row where each cell has a div with the title and the filter input. I've "hacked" this by making new dummy inputs and then fowarding the event handling to the existing filter row while keeping that row hidden. I don't think that's something that would get approved as a PR.

I'll ask my employer for permission to publish my base table that "has a" material-table that sorts most of these issues out along with a material-table fork with my PRs that make this hack work.

@AliTariq14
Copy link

@ingvaldlorentzen any solutions yo came up with, to use the main scroll ? like without the maxHeight ?

@ingvaldlorentzen
Copy link
Contributor

@ingvaldlorentzen any solutions yo came up with, to use the main scroll ? like without the maxHeight ?

No, not yet I'm afraid. If I do, I'll post any updates here!

@eclairsp
Copy link

eclairsp commented Mar 21, 2020

<MaterialTable
                    components={{
                        Container: props => (
                            <div style={{height: "60vh"}}> //same as maxBodyHeight
                                {props.children}
                            </div>
                        ),
                        Toolbar: props => null
                    }}
                    title={""}
                    columns={headers}
                    data={data}
                    parentChildData={(row, rows) =>
                        rows.find(a => a.Identifier === row.Parent)
                    }
                    options={{
                        search: false,
                        paging: false,
                        sorting: false,
                        draggable: false,
                        headerStyle: {position: "sticky", top: 0},
                        maxBodyHeight: "60vh"
                    }}
                >
</MaterialTable>

In my case making the height of the container(using the component prop) and maxBodyHeight same fixed it. I'm using the tree data, but I think it should work in other cases.

@stale
Copy link

stale bot commented Jul 5, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. You can reopen it if it required.

@stale stale bot added the wontfix This will not be worked on label Jul 5, 2020
@stale stale bot closed this as completed Jul 12, 2020
@ZakKa89
Copy link

ZakKa89 commented Jul 24, 2020

I really feel like the filter row should be part of the header. We are also trying to make it sticky but no luck because of it's DOM position.

@lepusarcticus
Copy link

Is there any way to do this without setting the maxBodyHeight ?

I have a table (without pagination) in a view, where I want a sticky header. But when setting maxBodyHeight this creates a new scrollbar within the table. I want the main scrollbar to do the scrolling.

Is this possible at the moment? Any tips?

Hi @ingvaldlorentzen, I am also facing the same issue. Have you figured out any solution for this?

@ingvaldlorentzen
Copy link
Contributor

No, I never found a good solution.

We've largely solved the underlying UX issue by providing robust filtering and sorting features in the tables.

@lepusarcticus
Copy link

No, I never found a good solution.

We've largely solved the underlying UX issue by providing robust filtering and sorting features in the tables.

Okay, @ingvaldlorentzen. Thanks for your response!

@twisterminjon
Copy link

For me I have this problem if I want to stick header and first colum. I've made in that way:

  1. Not using default way of sticking the column
  2. For the first column made
    cellStyle : {
    backgroundColor: 'white',
    position: 'sticky',
    left: 0,
    zIndex: 1,
    },
    headerStyle: {
    left: '0px',
    zIndex: 3
    }
  3. In the component use this option
    headerStyle: {position: "sticky", top: 0, zIndex: 2},

In this way I have only one scrool bar.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature help wanted Extra attention is needed wontfix This will not be worked on
Projects
None yet
Development

No branches or pull requests