telekom / scale

Scale is the digital design system for Telekom products and experiences.
https://telekom.github.io/scale/
Other
374 stars 82 forks source link

DataGrid usage in React #739

Open rriedeltsi opened 2 years ago

rriedeltsi commented 2 years ago

Hi Scale-Team,

my setup is scale 3.0.0-beta.30 in a React (17) app.

Currently I explore how to use the DataGrid component. For embedding components in an ActionCell the docs suggest to provide HTML markup in the rows array like

label: { __html: '<scale-icon-action-more accessibility-title="More"></scale-icon-action-more>' },

Is there a way to directly use React components in ActionCells? I suppose that I could wrap my React components as webcomponents, announce them to the DOM and use them in the markup, but that's not really a feasible way for us.

Also, the same question came up for HTMLCells, where the docs suggest to use DOM functions to create HTML elements.

Regards (and thanks for the great work so far !!) Ralf

acstll commented 2 years ago

Hello @rriedeltsi thank you for your kind words!

Unfortunately there's no easy way to do this. As you have guessed, if you pass a React component directly, the web component (scale-data-grid in this case) will not know what to do with it or how to render it (since React components are abstract object/functions). This is definitely a known limitation with interoperability and web components.

You can only provide a string for the Action Cell, or a function that returns an actual DOM element for the HTML Cell.

I can think of the following ways, without having tested any of them (they're probably not feasible either):

For the HTML Cell you could try using React portals, where you provide a function that returns a DOM element where you render your React component with the portals API.

For the Actions Cell, would it be possible to use ReactDOMServer.renderToString(element)? So you could do label: { __html: renderToString(element) }.

Best regards.

rriedeltsi commented 2 years ago

Hi @acstll, thanks for the quick response! Actually, I was entrirely unaware of something like renderToString, and still not sure if I understand it fully :D

I tried this approach to create a FlyoutMenu into a ActionCell, and indeed the correct markup got rendered and the menu + items are drawn correctly. But, what I couln't figure out was how to attach event handlers with code from my app to the menu items to make them do something meaningful. As far as I understand what's going is that the event handlers are stripped away when using renderToString, and get reassigned "somewhere" later on (in a scenario where renderToString is used on the server side and the markup is magically inserted into the DOM on the client side).

Do you have a hint how to attach code to the event handlers for elements embedded within an ActionCell?

Cheers, Ralf

acstll commented 2 years ago

My pleasure, I'm glad it worked.

renderToString returns a string with HTML, it's simpler than you may think. Rendering React in the server and hydrating on the client is indeed something more complex. But your idea of hydrating is also correct :)

I wouldn't try hydrating the markup for the action cells though (I'm not too sure how that could work).

I would recommend you try and listen for events in the data grid element itself (sort of like an event delegation technique). All events from the flyout menu should bubble up, so you should be able to listen for scale-select or scale-close, etc. in the data grid, or even any close parent.

I hope that helps.

rriedeltsi commented 2 years ago

Hi @acstll ,

first of all wish you a happy new year!

Concerning my DataGrid problem - I'm getting closer but still not there ;-) Indeed I can see the events like scale-select bubbling up to the DataGrid element. What I'm still struggeling with is a proper way to include data (which row, which action, ...) into the event. My current approach is to (mis)use the id attrbute of the ScaleMenuFlyoutItem and encode those information into it, but it feels fishy and I'm sure there must be a better way to do this. Do you have an idea how this could be done better?

Cheers, Ralf

rriedeltsi commented 2 years ago

Hi @acstll ,

regarding my last comment, do you have a hint for me? Thanks in advance!

Cheers, Ralf