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

[Feature Request] DataTable -- ability to define per column data renderers decoupled from underlying data #1972

Open
ned2 opened this issue Mar 15, 2022 · 4 comments

Comments

@ned2
Copy link
Contributor

ned2 commented Mar 15, 2022

The DataTable component provides simple column rendering of numeric values leveraging D3 formatting. When other types of custom rendering is required you need to resort to performing transformations on the underlying data source being fed to the DataTable (eg using Pandas). This becomes a challenge when you want to allow the user to perform clientside filtering on the DataTable using the original data rather than the data transformed for display purposes.

A notable example of this is when you want to use Markdown rendering in the table (eg to convert text into hyperlinks) which currently requires supplying that column with a string containing markdown. A user filtering on this column will now be filtering on the Markdown text rather than the original raw string, which will run amok with the filtering behaviour expected by the user.

An additional issue is that users exporting the DataTable contents as a CSV etc will find that they have the Markdown strings in their columns rather than the original data values.

Here's a forum post I made on these challenges.

Idea for a possible solution flavour:

The DataTables jQuery plugin addresses this need by allowing columns to have a rendering attribute that defines custom rendering behaviour for each column that is independent of the underlying data. Perhaps the Dash DataTable could follow inspiration here, allowing the presentation attribute of columns to take a string that contains a JavaScript function which will be applied to the column's data for rendering, without changing the underlying data.

@alexcjohnson
Copy link
Contributor

@ned2 can you give some specific examples of the input data and resulting markdown string you want? We very much want to avoid writing JS functions in strings, as this can easily turn into a security risk, so I wonder if we could make do with a template string - perhaps involving multiple columns even, like "[{title}](/{slug})".

@ned2
Copy link
Contributor Author

ned2 commented Mar 18, 2022

For sure, some examples I have at the moment are:

  • http://google.com --> [http://google.com](http://google.com)
  • http://blah.com/assets/image.png --> ![alt text](http://blah.com/assets/image.png)
  • http://blah.com/media/movie.mp4 --> '<video src="http://blah.com/media/movie.mp4" controls>'

So you can see that the resulting markup in the transformed string is adding noise that can mess up the client-side filtering on those values. Possibly less of a concern for the first two examples, but the third is going to introduce false positive results for filtering on "controls" and "video".

I can very easily imagine other transformations that I or other folks might have that would introduce more of these kinds of filtering problems.

Not quite sure I follow how JavaScript in strings on the Dash server side would introduce a security risk. Isn't that how client-side callbacks currently work?

@alexcjohnson
Copy link
Contributor

OK great, all of those examples would be compatible with a template string approach.

The security concerns are a flavor of cross-site scripting (XSS). Clientside callbacks unambiguously came from the server, there's no way (without the app developer doing something REALLY weird) that these contain user input. But what we're talking about here would be part of a prop (presumably columns) and it's relatively easy for a malicious user to modify props in their own browser to contain whatever content they want. So all that's needed from the app is some mechanism that stores part or all of the layout on the server for another user to load - which is maybe not so common in public-facing apps, but it's quite common in enterprise apps. We have a whole package - snapshot engine - dedicated largely to this use case. Then the malicious user can see everything the other user is doing, and all their private data.

@ned2
Copy link
Contributor Author

ned2 commented Mar 30, 2022

@alexcjohnson, thanks heaps for taking the time to explain why exposing JavaScript strings as props to be evaluated would be a security risk. That makes sense to me now.

It sounds like you're proposing a new prop/column attribute that allows users to specify a simple templated string transformation? I think something along those lines would do the trick!

Is there anything I can do help get the ball rolling on this?

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

2 participants