react-data-table-component icon indicating copy to clipboard operation
react-data-table-component copied to clipboard

[FEATURE]: Pass adjacent rows to custom cell function

Open MikeWillis opened this issue 5 years ago • 8 comments

I am trying to pass adjacent rows to a custom cell function. Here are some details:

  • I have a table with a few columns, one of which has a "details" button
  • clicking the details button opens a modal that shows more of the data in the row
  • on that modal I would like two buttons, "next" and "previous" -- clicking these would allow us to show the details of the next or previous row

The reason the cell function needs to know about adjacent rows is because it opens / populates the modal by setting state.detailRow. The detailRow property is false by default, and if set to a row, the modal renders with the data in that row. If I can also set state.nextRow and state.prevRow, I can pass these to the modal, which can use them to pass the detail row back up.

Hope that all makes sense. I am new to React so there may be an easy way to do this already that I'm missing. I'll be working on this throughout the next few days so if I come up with something I'll make note here. Here are some pseudo-snippets that might make this more clear:

state = {
   detailRow: false
}
...
columns = [
   ...,
   {
      name: 'Details',
      cell: (row, index, column, id) => <div><button onClick={()=>{this.setState({detailRow:row})}}>Details</button></div>
   }
];
...
switchRow(row) {
   this.setState({detailRow:row});
}
closeModal() {
   this.setState({detailRow:false});
}
...
render(){
   return (
      ...
      {
         this.state.detailRow !== false &&
         <Modal
            title="Details"
            content=<Details row={this.state.detailRow} nextRow={this.state.nextRow} prevRow={this.state.prevRow} switchRow={this.switchRow} close={this.closeModal} />
         />
      }
      ...
   );
}

MikeWillis avatar Aug 31 '20 17:08 MikeWillis

I got this working on my own fork of this project, using a different method than above. The above method worked but I realized I could only switch rows up one or down one, because the passed nextRow and prevRow never changed. So nextRow and prevRow had to become child properties of row.

Works as desired, but I imagine this won't be good in terms of performance. Most rows now contain 3x as much data as they used to. In my case this isn't a big deal because the table isn't very heavy, but maybe there's a better way to go about this.

/src/DataTable/DataTable.js:

<TableBody
...
>
   {calculatedRows.map((row, i) => {
      ...
      row.prevRow = calculatedRows[i-1] || false;
      row.nextRow = calculatedRows[i+1] || false;

      return (
       <TableRow
         ...
      />
      ...
   })}

</TableBody>

MikeWillis avatar Aug 31 '20 20:08 MikeWillis

Why don’t you pass the data before submitting to data table in order to add links for next and previous rows? Then you only have one copy in memory

Mike Thomson Intelliflex Software Ph: 0431 817772


From: MikeWillis [email protected] Sent: Tuesday, September 1, 2020 6:46:10 AM To: jbetancur/react-data-table-component [email protected] Cc: Subscribed [email protected] Subject: Re: [jbetancur/react-data-table-component] [FEATURE]: Pass adjacent rows to custom cell function (#669)

I got this working on my own fork of this project, using a different method than above. The above method worked but I realized I could only switch rows up one or down one, because the passed nextRow and prevRow never changed. So nextRow and prevRow had to become child properties of row.

Works as desired, but I imagine this won't be good in terms of performance. Most rows now contain 3x as much data as they used to. In my case this isn't a big deal because the table isn't very heavy, but maybe there's a better way to go about this.

/src/DataTable/DataTable.js:

<TableBody ...

{calculatedRows.map((row, i) => { ... row.prevRow = calculatedRows[i-1] || false; row.nextRow = calculatedRows[i+1] || false;

  return (
   <TableRow
     ...
  />
  ...

})}

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHubhttps://github.com/jbetancur/react-data-table-component/issues/669#issuecomment-684029539, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AL6F6V6JH4FB55LEG5XPZFLSDQDZFANCNFSM4QQXKGTQ.

Intelliflex avatar Aug 31 '20 21:08 Intelliflex

@Intelliflex would that work if the table was re-sorted? I think the references would be all wrong then.

Another option is to store a copy of the original rows object in state, and pass just the keyField for the next/prev rows. Then on button click, display data from the rows object in state, rather than the datatable itself..

MikeWillis avatar Sep 01 '20 13:09 MikeWillis

Yes I expect sorting would be a problem. So you would have to pass again for each re sort.

Mike Thomson Intelliflex Software Ph: 0431 817772


From: MikeWillis [email protected] Sent: Tuesday, September 1, 2020 11:09:41 PM To: jbetancur/react-data-table-component [email protected] Cc: Mike Thomson [email protected]; Mention [email protected] Subject: Re: [jbetancur/react-data-table-component] [FEATURE]: Pass adjacent rows to custom cell function (#669)

@Intelliflexhttps://github.com/Intelliflex would that work if the table was re-sorted? I think the references would be all wrong then.

Another option is to store a copy of the original rows object in state, and pass just the keyField for the next/prev rows. Then on button click, display data from the rows object in state, rather than the datatable itself..

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/jbetancur/react-data-table-component/issues/669#issuecomment-684840453, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AL6F6V7TPVXTBVAG5VWL6H3SDTXBLANCNFSM4QQXKGTQ.

Intelliflex avatar Sep 02 '20 08:09 Intelliflex

@MikeWillis I see your dilemma. I wonder though if we could add a few extra props such as prevRow and nextRow to the columns Cell callback. I would need to investigate this but if it doesn't cause any performance issues we could implement it.

I'm not sure I have a lot of time this or next week to get this done with my schedule, but am open to PRs. In any case, I will tag this as a feature so it gets addressed at some point.

jbetancur avatar Sep 04 '20 13:09 jbetancur

@jbetancur sounds good! Right now I'm using the following method, which works but is not the ideal solution:

  • pass the next/prev keyField
  • display data from the original rows object based on the keyField

Will update here if I come up with a method like what you suggested

MikeWillis avatar Sep 08 '20 15:09 MikeWillis

@jbetancur I made some changes to my local branch, and prevRow / nextRow are now passed to the cell's custom callback function. The snag though is that when the detail modal is opened, it knows the current / prev / next rows, but nothing else. You can add a button to the detail modal to switch to the immediate prev/next rows, but no further.

It seems like the only way to do this is to make prev/next properties of the row object. That way every time the detail modal is switched to a new row, it always knows the prev/next rows for the current one.

Hope that makes sense, anyway I'm wondering if you have any thoughts on how to make it work without making prev/next properties of the row object.

MikeWillis avatar Sep 18 '20 01:09 MikeWillis

I have a somehow similar issue: I want to implement keyboard navigation in the table. It's easy to just store an index of the data that is passed to the table and incrementing or decrementing that index on key press.

That only works however when no sorting/filtering has happened. It would be easily solvable if calculatedRows could be accessed from outside of the data-table-component. Using a ref doesn't work as it's a function component. Is there any other way?

BenjaminHae avatar Dec 12 '20 08:12 BenjaminHae