Griddle icon indicating copy to clipboard operation
Griddle copied to clipboard

rowData not supplied to cutomComponent in v1.2

Open bristoljon opened this issue 7 years ago • 21 comments

Griddle version

1.2

Expected Behavior

CustomComponent receives rowData prop as in v0

Actual Behavior

customComponent only receives value and griddleKey

Steps to reproduce

const LinkToUser = props => {
  console.log('props', props); // { value: 'Adam Smith', griddleKey: 2 }
  const { value, rowData } = props;
  const url = '/users/${rowData.id}';
  return <Link to={url}>{value}</Link>;
};

...

<ColumnDefinition id="name" title="Name" order={1} customComponent={LinkToUser}  />

I understand it is possible to over-ride the CellContainer component to pass additional props down but I couldn't see a rowData selector to use.

This seems like a pretty standard requirement to make it possible to link an ID in another column etc. Only alternative is to use the ID field as the link to user..

Any help appreciated, thanks

bristoljon avatar Mar 24 '17 09:03 bristoljon

Did you figure out a way around this? I'm currently working around by closing over the containing data in render, e.g.

const { data } = this.props;

const CustomColumn = ({ value, griddleKey }) => {
  const objectId = _.get(data[griddleKey], '_id');
  return <Link to={`/objects/${objectId}`}>{value}</Link>;
};

But this is causing bugs for me as I'm getting undefined errors if the data prop changes - presumably as it's not being passed in as a prop to CustomColumn and so can be out of sync.

jamiecollinson avatar Mar 31 '17 09:03 jamiecollinson

The Storybook includes an example of enhancing a custom component with rowData: https://github.com/GriddleGriddle/Griddle/blob/90a46dbdcdeebca280f4b3d0f8a928f8ad7b9996/stories/index.js#L67-L71

const EnhanceWithRowData = connect((state, props) => ({
  rowData: rowDataSelector(state, props)
}));

const LinkToUser = EnhanceWithRowData(props => {
  console.log('props', props); // { value: 'Adam Smith', griddleKey: 2 }
  const { value, rowData } = props;
  const url = '/users/${rowData.id}';
  return <Link to={url}>{value}</Link>;
});

dahlbyk avatar Mar 31 '17 14:03 dahlbyk

@dahlbyk is correct. This is a deviation from how we were doing things in 0.x. We are currently taking an opt-in approach to this data for performance reasons. We are hoping to add a helper that is mostly that code provided as a util out of the box -- it seems like a use-case many people are bumping into.

We maybe could additionally make this something driven by a prop on CellDefinition too... something like <ColumnDefinition ..... includeRowData={true} />. I would love any additional thoughts around this.

ryanlanciaux avatar Mar 31 '17 18:03 ryanlanciaux

@ryanlanciaux - it certainly seems like a common use case. I guess about half of things I'd want to write a ColumnDefinition for would do plain cell formatting (e.g. formatting a date or adding styling), while the other half would need rowData (e.g. creating a fullName from forename and surname, creating an href from an id).

@dahlbyk - thanks for the link. I'm not using redux in my project but should be able to translate.

jamiecollinson avatar Apr 01 '17 06:04 jamiecollinson

Sorry, I was away and missed the responses until now.

I was looking into upgrading a project to 1.x but in the end we decided to leave things as they are so never got round to solving this.

I think the opt-in approach makes sense generally but it wasn't obvious how to go about this, even with the examples. Although I must have missed the example @dahlbyk pointed out, perhaps this would make a good standalone example for the docs rather than the more complicated ones provided?

@ryanlanciaux <ColumnDefinition ..... includeRowData={true} /> would certainly be easiest solution for us!

bristoljon avatar Apr 12 '17 07:04 bristoljon

<ColumnDefinition ..... includeRowData={true} /> would certainly be easiest solution for us!

This seems reasonable, but down the road there may be additional data that only certain columns need. How about include={['rowData']} with an extensibility point to specify how a given include key should be selected?

dahlbyk avatar Apr 13 '17 03:04 dahlbyk

That sounds like a good idea. My initial 2 second thought on this is that we'll make a bunch of enhancers for pulling things out of the store. The string passed into the array could refer to the key in the enhancer object. I'm thinking something like this..

{
  rowData: enhanceWithRowData ...,
  ...
  settings: enhanceWithSettings... // totally just made this one up
}

Then you could do something like <Griddle data={...} include={['rowData', 'settings']} /> and the code internally would say compose this stuff around this column (before it gets to customComponents).

ryanlanciaux avatar Apr 13 '17 18:04 ryanlanciaux

:+1:

To clarify, do you mean include on ColumnDefinition rather than Griddle? I suppose both could be supported.

Bonus points if there's a mechanism for plugins to inject additional enhancers.

dahlbyk avatar Apr 13 '17 19:04 dahlbyk

It would be also great if can support passing down props to cell such as props from react-router "match.url"

ieow avatar May 13 '17 13:05 ieow

It would be also great if can support passing down props to cell such as props from react-router "match.url"

ColumnDefinition does have extraData stubbed in, but it's not wired up yet. Would that be sufficient?

dahlbyk avatar May 14 '17 12:05 dahlbyk

Yupe, I think that would do.

ieow avatar May 14 '17 14:05 ieow

@ieow extraData has been implemented in https://github.com/GriddleGriddle/Griddle/pull/675.

dahlbyk avatar Jun 13 '17 15:06 dahlbyk

Sorry for late reply. I tried it, it works perfectly. Just may be the keyword 'cellProperties' is a bit long. :)

ieow avatar Jun 28 '17 10:06 ieow

Just may be the keyword 'cellProperties' is a bit long. :)

To clarify: after we have a release in npm with #675, values from extraData will be available directly in props. As you note, until then (and on older releases), you can pull extraData out of cellProperties.

dahlbyk avatar Jun 28 '17 19:06 dahlbyk

Cool.That is great. Can't wait for that.

ieow avatar Jul 02 '17 14:07 ieow

@ieow can you provide an example?

yasserzubair avatar Jul 26 '17 12:07 yasserzubair

@yasserzubair , I don't get what you need. What example you mean?

ieow avatar Jul 27 '17 14:07 ieow

I reqest an exmaple as well. Scenario is something like:

//testing customcpomponent
const ActionBar = () => {

  return (
    <div>
      <span><i className="fa fa-external-link" /></span>
      <span><i className="fa fa-arrow-right" /></span>
      <span><i className="fa fa-address-book" /></span>
    </div>
  );
}

and usage in render is:

 return(

      <div>

        <Griddle
          data={result}
          plugins={[plugins.LocalPlugin]}
        >

          <RowDefinition>

            <ColumnDefinition id="id"   />
            <ColumnDefinition id="createdAt" />
            <ColumnDefinition id="owner.name" title="Owner" />
            <ColumnDefinition id="recipient.name" title="recipient" />
            <ColumnDefinition id="total.amount" title="price"/>
            <ColumnDefinition title="actions" >
              <ActionBar />
            </ColumnDefinition>

          </RowDefinition>

        </Griddle>
      </div>
    );

janpauldahlke avatar Aug 01 '17 11:08 janpauldahlke

@janpauldahlke did you try something like this?

  ...
  <ColumnDefinition title="actions" customComponent={ActionBar} />
  ...

dahlbyk avatar Aug 01 '17 16:08 dahlbyk

@dahlbyk Hi :) so is there any way to get row data in customComponent of ColumnDefinition?

DmitryOlkhovoi avatar Mar 04 '18 11:03 DmitryOlkhovoi

Oh I see

const EnhanceWithRowData = connect((state, props) => ({
  rowData: selectors.rowDataSelector(state, props)
}));

A little bit heavy but fine, thx :)

DmitryOlkhovoi avatar Mar 04 '18 11:03 DmitryOlkhovoi