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 columns #848

Closed
visarts opened this issue Mar 8, 2018 · 70 comments
Closed

Sticky columns #848

visarts opened this issue Mar 8, 2018 · 70 comments

Comments

@visarts
Copy link

visarts commented Mar 8, 2018

Is there any plan to add a feature for fixed or 'sticky' columns allowing for horizontal scrolling, in addition to vertical

@rickevans
Copy link

I have this same problem as I would like to have the first two columns fixed in my table and have the rest of the table contents scroll

@x5engine
Copy link

x5engine commented Mar 8, 2018

nice to have

@gary-menzel
Copy link
Contributor

There are no sticky columns. The package needs a complete redesign for this. Sorry.

@OliverKK
Copy link

Hello @gary-menzel ,
can you estimate how much effort that would mean?
We are thinking about funding the development of the feature.
I think there are many users who might need this feature.

What are u guys think?
@jsonmaur
@sghall

@dvdhsu
Copy link

dvdhsu commented Apr 2, 2018

We would probably fund this with a few hundred $.

@gary-menzel
Copy link
Contributor

You'll have to talk to @tannerlinsley in regard to any paid-for development. My commercial rate is $100 per hour and I doubt a "few hours" will get this done as the whole architecture of ReactTable needs to be changed to do it (and I don't have the available hours to do a re-architect of RT). Seriously - if it were that easy it would already be done (others - including myself - have tried to do it in the current design and it just not feasible).

@tannerlinsley
Copy link
Collaborator

tannerlinsley commented Apr 2, 2018 via email

@tannerlinsley
Copy link
Collaborator

tannerlinsley commented Apr 2, 2018 via email

@dvdhsu
Copy link

dvdhsu commented Apr 2, 2018

Sorry - I didn't mean to imply a "few hours" would cut it - I know this is a big feature! But we would chip in a few hundred... and with 10 or so of us - that might be enough!

Agreed about open sourcing the results and checking with @tannerlinsley + @gary-menzel about it first.

So - is there anybody else willing to contribute?

@OliverKK
Copy link

OliverKK commented Apr 3, 2018

@dvdhsu
Yes. We are willing to contribute also.

What about starting a kickstarter project to fund this feature?

@JohanDuque
Copy link

It would be great to have not only the first column sticky but also a customisable one (the last one for example)

@ahmedhosny
Copy link

Great repo over here - but I opted to use scrollsync in react-virtualized for this specific purpose.

@x5engine
Copy link

@ahmedhosny yes looks the same as I did but that is too much extra code for just one simple thing that can be done without adding any extra library...

@GuillaumeJasmin
Copy link

Hi,
I juste release my workaround, with demo here:
https://guillaumejasmin.github.io/react-table-hoc-fixed-columns/

It's a simple HOC, with some tricks. I know it's not the best solution, but it work now, and I think it can be useful for others people here. It could be use until a full support of fixed columns in ReactTable. I haven't used it with more complex table, so feedback will be appreciated.

I release it for $0, amazing, no ? ;)
ReactTable is an amazing tool, I tried many others table tools before find it, and there no equivalent. I don't understand developers who use it and want money to contribute. You should be satisfied that ReactTable was shared, stop abuse !

@OliverKK
Copy link

OliverKK commented Apr 20, 2018

Hi @GuillaumeJasmin ,
thank you. The first tests passed so far. I'll give it a try.
I will have a closer look at the extension in the next days.

UPDATE:
@GuillaumeJasmin Thank you for your effort to implement the sticky column HOC. It works greate.

@meteorplus
Thank you for your efford too. I will have a look at your implementation as well, as soon as it is available 👍

Kind regards

@x5engine
Copy link

x5engine commented Apr 23, 2018

@GuillaumeJasmin thanks mate but listen I never abused anyone! even the author suggested a hourely rate before I jumped in and even @OliverKK offered to fund this!

and keep in mind not everyone has a stable job or a monthly salary...

we hustle like this so we can pay our bills, and this is how open source works!

otherwise, I am gonna release this into my repo https://github.com/meteorplus/react-table for free, I don't give a fuck if it wasn't for my rent else I won't care.

edit: my solution doesn't involve a new component or anything more just pure CSS and has two options fixed vertical and horizontal columns!

@Oleksandr-Silin
Copy link

@meteorplus Hey, just wondering, have you released your changes?

@pmusaraj
Copy link

I wound up using a semi-simple solution to do this for one frozen column (Guillaume's HOC supports multiple), it involves a few steps:

  1. In your column's definition, add className: 'frozen' and headerClassName: 'frozen'.

  2. In your css add the following:

      .rt-tr {
        position: relative;
      }
      .frozen {
        position: absolute;
        left: 0px;
        background: #F8F8F8;
        height: 36px;
        transition: left 0.2s;
      }

      .rt-th.frozen {
        z-index: 2;
        height: 34px;
      }

(YMMV, some of the styles above are specific to my use. Like the height of the cells, for example. You may also need to add some more styles to make this work with striping and highlighting.)

  1. Add a callback to the ReactTable's onResizedChange. For example:
        <ReactTable
          onResizedChange={_.debounce(this.onTableResizeChange, 10)} 
          ... />

(Notice that I'm using Underscore's debounce to avoid calling this too often on a resize.)
And the onTableResizeChange looks like this:

  onTableResizeChange(params) {
    let frozenCol = this.state.frozenColumn,
        padLeft = 0;

    if (frozenCol) {
      if (params && params[0].id === frozenCol) {
        padLeft = params[0].value;
      } else {
        padLeft = $('.ReactTable .rt-th.frozen').width() + 10;
      }

      $('.ReactTable .rt-tr').css('padding-left', padLeft + 10);
    } else {
      $('.ReactTable .rt-tr').css('padding-left', 0);
    }
  }

So, this will make sure that the frozen column can be resized and that the other table columns will adjust accordingly.

  1. Final step: add an onScroll event to the table properties, and then change the position of the absolutely positioned column, so that it looks frozen in place.
      <ReactTable
          getTableProps={() => {
            return {
              onScroll: (e) => {
                if (this.state.frozenColumn) {
                  if (this.tableScrollTop === e.target.scrollTop) {
                    let left = e.target.scrollLeft > 0 ? e.target.scrollLeft - 12 : e.target.scrollLeft;
                    $('.ReactTable .rt-tr .frozen').css({left: left});
                  } else {
                    this.tableScrollTop = e.target.scrollTop;
                  }
                }
              }
            };
          }}
      ... />

Note that the onScroll relies on this.tableScrollTop to only change the position of the frozen elements when scrolling horizontally. this.tableScrolltop is initialized in the constructor, like so:

  constructor(props){
    super(props);
    this.tableScrollTop = 0;
  }

@krzysiek1507
Copy link

krzysiek1507 commented May 10, 2018

You can use position: sticky to do it. Example (please check css file)

@datanotion
Copy link

The solution from @krzysiek1507 worked for me. Next I'm going to try to determine how to freeze the grouping header as well. Thank you!

@krzysiek1507
Copy link

You're welcome!

@datanotion you can try this!

@krzysiek1507
Copy link

No, it doesn't work. Sorry! It breaks the table!

There is a problem with overflow: auto and position: sticky. Maybe some CSS master can fix it.

@x5engine
Copy link

x5engine commented May 11, 2018

@krzysiek1507 @Oleksandr-Silin here is my solution

https://codesandbox.io/s/pk19p2pm17
The first column is locked I don't have time to add it to the repo but you have the whole css there working fine with all browsers out there no stick or fancy css.

If I find the other horizontal lock for the first rows I will post it here too thanks.
Enjoy for free!

@GuillaumeJasmin
Copy link

I currently work on support of fixed group header in react-table-hoc-fixed-columns . I think release it in few days.

@pmusaraj
Copy link

pmusaraj commented May 16, 2018

I worked on a slightly lighter and better solution (mostly due to a bug in Safari). Here is the sandbox: https://codesandbox.io/s/k9n3y82wov

I tested on Safari/Chrome/Firefox. The frozen column can be any column, and all columns can be resized.

@tannerlinsley
Copy link
Collaborator

There is no direct roadmap to support Sticky Columns in the latest version of React Table.

@GuillaumeJasmin
Copy link

GuillaumeJasmin commented Jul 13, 2018

Hi,
I released a v1 beta of react-table-hoc-fixed-columns.

New features

  • fixed columns groups
  • fixed columns on the left and/or right side
  • complete refactoring, no more DOM and CSS hacks, so better performances

You can install it with the tag next:

npm install react-table-hoc-fixed-columns@next

Demo

https://codesandbox.io/s/jnjv6j495y

Release note

https://github.com/GuillaumeJasmin/react-table-hoc-fixed-columns/releases/tag/v1.0.0-beta.3

Docs

https://github.com/GuillaumeJasmin/react-table-hoc-fixed-columns/tree/next

@timendez
Copy link

Using position: sticky will work as per @krzysiek1507's example, and you can polyfill for unsupported browsers with https://github.com/wilddeer/stickyfill

@GuillaumeJasmin
Copy link

position: sticky doesn't work for me with 2 fixed columns, or with fixed groups

@ailequal
Copy link

I am working with "@tanstack/table-core": "8.2.6" and I was able to stick a column to either left or right by following this example "https://stackoverflow.com/a/53526213/19879825". Just some CSS rules and the table seems to keep working fine.

@x5engine
Copy link

x5engine commented Apr 6, 2023

Hello guys, so what solution did you choose?

@sanjay-git
Copy link

is there any implementation with v8?

You just have to add position sticky to pinned columns themselves, and use the "start" properties on a column's left css

You'll get something like this https://www.material-react-table.dev/?path=/story/features-column-pinning-examples--column-pinning-initial

@KevinVandy, could you expand a bit more on what you mean by "start" properties ? I am trying to add sticky behavior to more than one column, but finding it difficult to set the 'left' property for columns other than the first one. Thanks in advance!

@paweljurczynskiflyr
Copy link

paweljurczynskiflyr commented Jun 8, 2023

is there any implementation with v8?

You just have to add position sticky to pinned columns themselves, and use the "start" properties on a column's left css
You'll get something like this https://www.material-react-table.dev/?path=/story/features-column-pinning-examples--column-pinning-initial

@KevinVandy, could you expand a bit more on what you mean by "start" properties ? I am trying to add sticky behavior to more than one column, but finding it difficult to set the 'left' property for columns other than the first one. Thanks in advance!

I'm on a similar problem right now. And I just thinking about setting ref to get the physical element and get that offsetLeft. And for async rendering use resizeObserver and update that accordingly.

I'm not sure if it's a best solution at this moment 😢

@HurYur
Copy link

HurYur commented Aug 4, 2023

I was expecting that Column Pinning would stick the column to the side during the horizontal scrolling, but it doesn't do it as well.

@Husain010
Copy link

I was expecting that Column Pinning would stick the column to the side during the horizontal scrolling, but it doesn't do it as well.

Any workarounds? I want to achieve the same but cannot find anything

@KevinVandy
Copy link
Member

I was expecting that Column Pinning would stick the column to the side during the horizontal scrolling, but it doesn't do it as well.

Any workarounds? I want to achieve the same but cannot find anything

You have to provide the CSS to do that yourself, of course. Position sticky and all that. TanStack Table keeps track of which columns are pinned

@Husain010
Copy link

I was expecting that Column Pinning would stick the column to the side during the horizontal scrolling, but it doesn't do it as well.

Any workarounds? I want to achieve the same but cannot find anything

You have to provide the CSS to do that yourself, of course. Position sticky and all that. TanStack Table keeps track of which columns are pinned

I actually was able to achieve it with CSS itself! No pinning also required ( Had to have the right 0hand most column sticky for horizontal scroll)

@GlebKodrik
Copy link

GlebKodrik commented Oct 17, 2023

If you don't mind, please show me how you fixed the columns in the codesandbox or another sandbox (for tanstack-table)

I've been trying to do this for a long time and it doesn't work at all. I would really appreciate some help

@Nikolic-Marko
Copy link

Hi guys, same issue here. I see that this was discussed 5years ago, are there any plans maybe to implement this now on version 8, or should we go with the hacky solution?

@mpcen
Copy link

mpcen commented Nov 4, 2023

It's 2023. We need this feature

@tannerlinsley
Copy link
Collaborator

tannerlinsley commented Nov 4, 2023 via email

@mpcen
Copy link

mpcen commented Nov 9, 2023

What’s stopping you from putting a sticky style on the first column cells? We do this and it works just fine. Tanner Linsley

On Nov 4, 2023 at 9:26 AM -0600, Manny Martinez @.>, wrote: It's 2023. We need this feature — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you were mentioned.Message ID: @.>

just seems like a hack tbh. im able to successfully sticky 1 column but having trouble stickying multiple

@andresgutgon
Copy link

What’s stopping you from putting a sticky style on the first column cells? We do this and it works just fine.

We have a virtualized table. Would be that a solution in that case?

@tomasmenezes
Copy link

+1, The process could be facilitated for multi-column pinning styling and virtualization cases

@Khangeldy
Copy link

If someone want multiple sticky columns. You can use getStart method on columns. I found it accidently on documentation. And there no mention about it.
Fast example:

const sticky = ['name', 'age']
...
headers.map(header => {
return <th style={sticky.includes(header.id) ? {{ left:  header.getStart('left'), position: 'sticky', top: 0 } : {}}>{header.column.columnDef.header}</th>

You are welcome ! Thanks to great library 👍

@GlebKodrik
Copy link

GlebKodrik commented Dec 3, 2023

Here is my solution for docked columns https://github.com/GlebKodrik/table

There in the readme there is a link to the assembly, which you can follow and see whether or not. In this link, the column has a menu “Fix column”, you can poke it and try scroll

@Florinstruct
Copy link

Here is my solution for docked columns https://github.com/GlebKodrik/table

There in the readme there is a link to the assembly, which you can follow and see whether or not. In this link, the column has a menu “Fix column”, you can poke it and try scroll

How do I find the "Fix column" without learning Russian?

@andresgutgon
Copy link

How do I find the "Fix column" without learning Russian?

Not the way to go in an Open Source community imo. @GlebKodrik give us a solution. We can look into the code which is still javascript.

@Florinstruct
Copy link

How do I find the "Fix column" without learning Russian?

Not the way to go in an Open Source community imo. @GlebKodrik give us a solution. We can look into the code which is still javascript.

Well if you can't follow the example because it's in Russian that's a problem.

@andresgutgon
Copy link

But you know how to read javascript. Don't you?

@Florinstruct
Copy link

But you know how to read javascript. Don't you?

I'm not quite sure why you're trying to turn this into a cake fight. @GlebKodrik posted an example that is not usable unless you speak Russian so I asked how to find the button he mentioned. If you can't help with that, please don't post toxic comments at me.

@andresgutgon
Copy link

andresgutgon commented Dec 11, 2023

You're right, I don't want to make this thread a toxic place. So I'll stop talking. Just for clarification I started this discussion because the way you speak to him sounded not ok

How do I find the "Fix column" without learning Russian?

That you don't know Russian (neither do I) is not his problem. He did a great work finding a solution. We can just look into the code. To me this is so obvious that I can't understand why we're having this discussion in the first place.

Anyway, again you're right I'm not helping here so I'll stop talking. Sorry to the rest 🙏

@GlebKodrik
Copy link

GlebKodrik commented Dec 26, 2023

If you want to see the visual part, I have translated everything into English. If you don’t understand how to reproduce cases on the site (because it’s Russian), just translate the page

If we are talking about code, then there are no problems there, JavaScript

Also, if you debug everything, you can find it without knowing the language
I just decided to show the solution I managed to make

Main component src/components/Table

@edprats
Copy link

edprats commented Jan 21, 2024

going to post this hacky solution in case it helps anyone in the future

in my situation i wanted to just have the first column always sticky on scroll so i added a custom-column-sticky css class to the td element.

and the css is the following:

td:first-of-type.custom-column-sticky {
  position: sticky;
  left: 0;
  top: 0;
}

@SurendarSingh
Copy link

You can add sticky properties for a column in the className into column meta.

import "@tanstack/react-table";
import { RowData } from "@tanstack/react-table";

declare module "@tanstack/react-table" {
  interface ColumnMeta<TData extends RowData, TValue> {
    className: string;
  }
}

const columns = [
    {
      header: "Sticky Column",
      accessorKey: "stickyColumn",
      meta: {
        className:
          "sticky right-0",
       },
    },
// other columns
]



//Then, you can get it through the column.columnDef.meta?.className. Add the className in th and td tag.
<th
className={`${
header.column.columnDef.meta?.className ?? ""
} 
// other tailwind CSS properties
`}
key={header.id}
colSpan={header.colSpan}
>
<td
key={cell.id}
className={`${
cell.column.columnDef.meta?.className ?? ""
} 
// other tailwind CSS properties
`}
>

@donlair
Copy link

donlair commented Feb 21, 2024

I was just working on this issue and put together a small repo to demonstrate my solution that allows you to make multiple columns sticky:

CleanShot 2024-02-21 at 13 12 20

@KevinVandy
Copy link
Member

I was just working on this issue and put together a small repo to demonstrate my solution that allows you to make multiple columns sticky:

CleanShot 2024-02-21 at 13 12 20

There's also an official example for sticky column pinning in the docs
https://tanstack.com/table/latest/docs/framework/react/examples/column-pinning-sticky

@Ignacio1996
Copy link

Hey all, without making any changes to react-table, we found a very simple solution:

Just create 2 tables, one with one column, the other with the rest of your columns and an horizontal overflow container.

This fixes the issue, we know it's not the best solution, and the latest version of react-table probably has a fix for this. But if you're using an older version (we are), 2 tables is the answer. Make sure that each table has it's own div container, and the do a flex-row for the container of the 2 tables.

Hope that helps!

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

No branches or pull requests