Skip to content
This repository was archived by the owner on Jun 22, 2019. It is now read-only.

WIP - enable components as cells #11

Closed
wants to merge 2 commits into from
Closed

WIP - enable components as cells #11

wants to merge 2 commits into from

Conversation

chriddyp
Copy link
Member

@chriddyp chriddyp commented Oct 17, 2017

render anything inside cells: links, graphs, dropdowns, whatever!
enabled by plotly/dash-renderer#26
would fix #6 and #7

usage (requires plotly/dash-renderer#26)

# -*- coding: UTF-8 -*-

import dash
from dash.dependencies import Input, Output, State
import dash_core_components as dcc
import dash_html_components as html
import dash_table_experiments as dt
import json
import pandas as pd
import plotly

app = dash.Dash()

app.scripts.config.serve_locally = True

DF_GAPMINDER = pd.read_csv(
    'https://raw.githubusercontent.com/plotly/datasets/master/gapminderDataFiveYear.csv'
)
sparklines = {
    c: html.Div(style={'height': 100, 'width': '100%'}, children=dcc.Graph(
        id=c,
        figure={
            'data': [{
                'x': DF_GAPMINDER[c],
                'type': 'histogram'
            }],
            'layout': {
                'height': 100,
                'width': 150,
                'margin': {
                    'l': 0, 'r': 0, 't': 0, 'b': 0
                },
                'xaxis': {
                    'showticklabels': False,
                    'showline': False,
                    'showgrid': False,
                },
                'yaxis': {
                    'showticklabels': False,
                    'showline': False,
                    'showgrid': False,
                }
            }
        },
        config={'displayModeBar': False}
    ))
    for c in DF_GAPMINDER.columns
}

app.layout = html.Div([
    html.H1('💖 Dash Sparklines 💖', style={'textAlign': 'center'}),
    html.H2(html.I('Coming Soon'), style={'textAlign': 'center'}),
    dt.DataTable(
        rows=[sparklines] + DF_GAPMINDER.to_dict('records'),
        id='table',
        min_height=1500,
    ),
    html.Div(dcc.Dropdown(), style={'display': 'none'})
], className="container")


app.css.append_css({
    "external_url": "https://codepen.io/chriddyp/pen/bWLwgP.css"
})

if __name__ == '__main__':
    app.run_server(debug=True, port=8060)

sparklines

@richard-muir
Copy link

Yes! This looks incredible :-)

@chriddyp chriddyp changed the title enable components as cells WIP - enable components as cells Oct 23, 2017
@BAjayiobe1
Copy link

Fantastic! This would be really useful for the project I'm currently working.

@jdagdelen
Copy link

I heartily support this feature as well.

@gustavengstrom
Copy link

This seems like a great update! I would like to try this out asap... I tried to do a: pip install git+https://github.com/plotly/dash-table-experiments.git@sub-renderer
Cannot get the above example to work... Only Error response is: Error loading layout. Any ideas on what I may be doing wrong?!

@chriddyp
Copy link
Member Author

chriddyp commented Dec 14, 2017

I tried to do a: pip install
pip install git+https://github.com/plotly/dash-table-experiments.git@sub-renderer

This repo doesn't contain the necessary JS and CSS bundles. You'll have to build them locally:

git clone https://github.com/plotly/dash-table-experiments
cd dash-table-experiments
git checkout sub-renderer
npm i
npm run prepublish
python setup.py sdist
pip install dist/dash_table_experiments-0.5.0.tar.gz # or whatever version it is

and you'll need to build the dash-renderer package

git clone https://github.com/plotly/dash-renderer
cd dash-renderer
git checkout  components-as-props
npm i
npm run prepublish
python setup.py sdist
pip install dist/dash_renderer-0.11.1.tar.gz # or whatever version it is

and then you'll need to make sure that it's assets are loaded locally with

app.scripts.serve_locally=True

@gustavengstrom
Copy link

Thanks for the quick reply! I followed these instructions but I still get: Error loading layout. You wrote that usage (requires plotly/dash-renderer#26). Do I also need to build dash-renderer locally??

@chriddyp
Copy link
Member Author

Do I also need to build dash-renderer locally??

Yeah, that one too. Same steps for that repo as well

@chriddyp
Copy link
Member Author

I have just updated this PR to support a new prototype of dash-renderer: plotly/dash-renderer#32.

The same functionality as mentioned in #11 (comment) still applies, this is just a more performant and generic solution.

@chriddyp
Copy link
Member Author

chriddyp commented Dec 15, 2017

Updated Examples

Sparklines
image

import dash
from dash.dependencies import Input, Output, State
import dash_core_components as dcc
import dash_html_components as html
import dash_table_experiments as dt
import json
import pandas as pd
import numpy as np
import plotly

app = dash.Dash()
server = app.server

app.scripts.config.serve_locally = True
app.css.config.serve_locally = True

DF_GAPMINDER = pd.read_csv(
    'https://raw.githubusercontent.com/plotly/datasets/master/gapminderDataFiveYear.csv'
)

ROW_HEIGHT = 40

sparklines = {
    c: html.Div(style={'height': 100, 'width': '100%'}, children=dcc.Graph(
        id=c,
        figure={
            'data': [{
                'x': DF_GAPMINDER[c],
                'type': 'histogram',
            }],
            'layout': {
                'height': ROW_HEIGHT,
                'margin': {
                    'l': 0, 'r': 0, 't': 0, 'b': 0
                },
                'xaxis': {
                    'showticklabels': False,
                    'showline': False,
                    'showgrid': False,
                },
                'yaxis': {
                    'showticklabels': False,
                    'showline': False,
                    'showgrid': False,
                },
                'hovermode': 'closest'
            }
        },
        config={'displayModeBar': False}
    ))
    for c in DF_GAPMINDER.columns
}

ROWS = [sparklines] + DF_GAPMINDER.to_dict('records')

app.layout = html.Div([
    dt.DataTable(
        rows=ROWS,

        row_selectable=True,
        filterable=True,
        sortable=True,
        selected_row_indices=[],
        id='datatable',

        row_height=ROW_HEIGHT
    ),
    html.Div(id='selected-indexes'),
    dcc.Graph(
        id='graph-gapminder'
    ),
], className="container")


app.css.append_css({
    "external_url": "https://codepen.io/chriddyp/pen/bWLwgP.css"
})

if __name__ == '__main__':
    app.run_server(debug=True)

Conditional Formatting
image

import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_table_experiments as dt

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(50, 4), columns=list('ABCD'))

COLORS = [
    {
        'background': '#fef0d9',
        'text': 'rgb(30, 30, 30)'
    },
    {
        'background': '#fdcc8a',
        'text': 'rgb(30, 30, 30)'
    },
    {
        'background': '#fc8d59',
        'text': 'rgb(30, 30, 30)'
    },
    {
        'background': '#d7301f',
        'text': 'rgb(30, 30, 30)'
    },
]


def is_numeric(value):
    try:
        float(value)
        return True
    except ValueError:
        return False


def cell_style(value, min_value, max_value):
    style = {}
    if is_numeric(value):
        relative_value = (value - min_value) / (max_value - min_value)
        if relative_value <= 0.25:
            style = {
                'backgroundColor': COLORS[0]['background'],
                'color': COLORS[0]['text']
            }
        elif relative_value <= 0.5:
            style = {
                'backgroundColor': COLORS[1]['background'],
                'color': COLORS[1]['text']
            }
        elif relative_value <= 0.75:
            style = {
                'backgroundColor': COLORS[2]['background'],
                'color': COLORS[2]['text']
            }
        elif relative_value <= 1:
            style = {
                'backgroundColor': COLORS[3]['background'],
                'color': COLORS[3]['text']
            }
    return style


def ConditionalTable(dataframe):
    max_value = df.max(numeric_only=True).max()
    min_value = df.min(numeric_only=True).max()
    rows = []
    for i in range(len(dataframe)):
        row = {}
        for col in dataframe.columns:
            value = dataframe.iloc[i][col]
            style = cell_style(value, min_value, max_value)
            row[col] = html.Div(
                value,
                style=dict({
                    'height': '100%'
                }, **style)
            )
        rows.append(row)

    return rows


app = dash.Dash()

app.scripts.config.serve_locally = True
app.css.config.serve_locally = True

app.layout = html.Div([
    dt.DataTable(
        rows=ConditionalTable(df),

        row_selectable=True,
        filterable=True,
        sortable=True,
        selected_row_indices=[],
        id='datatable',
    )
], className='container')

if __name__ == '__main__':
    app.run_server(debug=True)

@chriddyp
Copy link
Member Author

I just published some prerelease versions of this code. Try out the example above by installing these packages:

pip install dash==0.19.0
pip install dash-core-components==0.16.0rc1
pip install dash-html-components==0.9.0rc1
pip install dash-renderer==0.13.0rc2
pip install dash-table-experiments==0.6.0rc1

@gustavengstrom
Copy link

Nice! I have tested adding images which works great! Could the above script be used to also change column widths conditionally?! I think this is would be an important feature to add...

@gustavengstrom
Copy link

gustavengstrom commented Dec 22, 2017

Noticed a problem in the above prelease. The header row became scrollable and partially hided the first column header when running the above code with: app.css.config.serve_locally = False. While searching for the error I noticed that the following dash_table_experiments.css is not being served as it should at:

https://unpkg.com/[email protected]/dash_table_experiments/dash_table_experiments.css

@chriddyp
Copy link
Member Author

Could the above script be used to also change column widths conditionally

It can't, but I just added this in #33 and #32 🍻

@annitrolla
Copy link

Does not seem to render links properly: href attribute goes missing.
I took the example from #11 (comment) and swapped the graph-drawing part to

sparklines = {
    c: html.Div(style={'height': 100, 'width': '100%'}, children=[
        dcc.Link('Navigate to "/"', href="http://www.google.com")
    ])
    for c in DF_GAPMINDER.columns
}

the resulting HTML inside a cell is

<a>Navigate to "/"</a>

@chriddyp
Copy link
Member Author

@annitrolla - Use html.A instead for links that are for 3rd party websites. dcc.Link is only used for links within Dash, and it has to be used with a dcc.Location component (see https://plot.ly/dash/urls for more examples).

@annitrolla
Copy link

@chriddyp The external links with html.A worked, thanks! However, I try to render table cells as links within Dash, but I keep getting Error loading dependencies. The only modified parts are:

sparklines = {
    c: html.Div(children=[dcc.Link(
        'Navigate to "/page-2"', href='/page-2'
    ),
        dcc.Location(id='url', refresh=False),
        html.Div(id='page-content')
    ])
    for c in DF_GAPMINDER.columns
}

and

@app.callback(Output('page-content', 'children'),
              [Input('url', 'pathname')])
def display_page(pathname):
    return html.Div([
        html.H3('You are on page {}'.format(pathname))
    ])

@gustavengstrom
Copy link

@chriddyp: Any plans for when this branch will be merged?! My project needs both the column width adjustment of 0.5.3 and the ability to enable components as cells but the above prerelease came prior to 0.5.3. If not ready to merge yet perhaps an update to the prerelease?! Thanks!

@mankensin
Copy link

@chriddyp, Thanks for the great improvements on DataTable. I am also new to Dash and trying to implement the Conditional Formatting in your example above. Everything works fine but the Filter rows does not work. Is there anything I am missing?
capture

@chriddyp
Copy link
Member Author

Everything works fine but the Filter rows does not work. Is there anything I am missing?

I don't think that you are missing anything. My guess is that this just doesn't work yet. There is quite a lot of work required to tie everything together.

@mankensin
Copy link

@chriddyp, thanks for your prompt response. That was highly appreciated!

@mankensin
Copy link

I have an html file rendered from DataFrame, is there a way I can open this html directly on Dash?

@mankensin
Copy link

Please can someone help me with how to render html file directly on Dash? e.g

app.layout = html.Div(
html.Iframe(src='/home/makinde/test2.html')
)

@chriddyp
Copy link
Member Author

@mankensin - These questions are not related to this particular PR. Please ask these questions on the community forum: https://community.plot.ly/c/dash

@FarrandTom
Copy link

Hey @chriddyp,

Any idea of a timeline on when this will be merged with the master branch?

This functionality is too good to pass up for my app!

Cheers, Tom!

@chriddyp
Copy link
Member Author

Any idea of a timeline on when this will be merged with the master branch?

It's going to be a long time still. This PR is just a POC, to bring this into production will require a lot of deeper changes across Dash

@FarrandTom
Copy link

FarrandTom commented Mar 1, 2018 via email

@pbosavage
Copy link

pbosavage commented Mar 19, 2018

@chriddyp - I'm learning dash right now -- I'm very impressed and looking forward to what I can construct once proficient. I'm very interested in the Conditional Formatting example shown above. That particular feature would really help. I can't, however, get out of the gate when it comes to upgrading the packages. I've taken a working dash application that constructs a DTE DataTable to apply the conditional formatting to. I started by upgrading the packages -

pip install dash==0.19.0
pip install dash-core-components==0.16.0rc1
pip install dash-html-components==0.9.0rc1
pip install dash-renderer==0.13.0rc2
pip install dash-table-experiments==0.6.0rc1

  • then seeing if the application behaves the same way before applying the conditional formatting. The application starts without error, but the browser responds with 'Error loading dependencies'. The javascript console shows:

Error: Minified React error #137; visit http://facebook.github.io/react/docs/error-decoder.html?invariant=137&args[]=br&args[]= for the full message or use the non-minified dev environment for full errors and additional helpful warnings.
at r (react-dom.min.js:15)
at o (react-dom.min.js:13)
at h.mountComponent (react-dom.min.js:13)
at Object.mountComponent (react-dom.min.js:14)
at performInitialMount (react-dom.min.js:13)
at p.mountComponent (react-dom.min.js:13)
at Object.mountComponent (react-dom.min.js:14)
at performInitialMount (react-dom.min.js:13)
at p.mountComponent (react-dom.min.js:13)
at Object.mountComponent (react-dom.min.js:14)

There are no errors on the application console. It seems like simply installing the new packages causes the problem. Are there other packages that need to be installed or upgraded that I am missing?

Thanks & regards,

Update - I found that I also get the following on the javascript console:

Refused to apply style from 'https://unpkg.com/[email protected]/dash_table_experiments/dash_table_experiments.css' because its MIME type ('text/plain') is not a supported stylesheet MIME type, and strict MIME checking is enabled.

@chriddyp - Is there anything new on this front? It would be a huge benefit.

@rmarren1
Copy link

^ I am having the same problem, this seems only usable with app.css.config.serve_locally = True at the moment.

@Pastryman
Copy link

Hi! I have taken a look at the example code, but don't immediately see if this could be the solution to my problem. My situation is as follows:

  • I have a column, let's call it 'star_score', containing an int in the range [0,5]
  • For each of the possible scores I have a image star_score_x.png (x = range(0,5))
  • I want a column in my table showing the image corresponding to the star score of that row

Would this be possible?

@udhayasankari
Copy link

@chriddyp I was using this feature to add colors to cell based on values. I tried using the pre-release version specified by you as below.

pip install dash==0.19.0
pip install dash-core-components==0.16.0rc1
pip install dash-html-components==0.9.0rc1
pip install dash-renderer==0.13.0rc2
pip install dash-table-experiments==0.6.0rc1

Example given above works like charm. I would also need arguments in dash-table-experiments column_widths. Also enable_drag_and_drop isn't working in above versions.

But when I use dash-table-experiments==0.6.0 , column_widths and drap_and_drop features are working. But my color code is not rendering. Could

Is there any option to get both ? :(

@nevenpiculjan
Copy link

When I install dependencies written below, everything is rendered well inside the table cells and above table examples from the post work well, but that combination of dependencies makes plots not rendered well (lines are missing from the last plot in subplot).

pip install dash==0.19.0
pip install dash-core-components==0.16.0rc1
pip install dash-html-components==0.9.0rc1
pip install dash-renderer==0.13.0rc2
pip install dash-table-experiments==0.6.0rc1

When do you plan to make this part stable?

@popohoma
Copy link

Hi Chris,

I have followed your Conditional Formatting 100% in Python but it's giving me following error in IE.

Error Loading Dependencies

Is this related to my Python 3.6 version?

Thanks,

Allen

@northcuttc52
Copy link

Hi Chris,

I am not able to set the column_widths=[] or use resizable=True for my DataTable. I have tried:

pip install dash-renderer==0.13.0rc2
pip install dash-table-experiments==0.6.0rc1

and

pip install dash-renderer==0.13.0
pip install dash-table-experiments==0.6.0

The later version of data-table-experiments lets me use the column_widths option, however, the columns aren't actually resized. I am rendering html.Div elements within the DataTable. I also started getting some dependency errors on the later versions above.

Really great stuff you guys are doing here!!

@osmancakir
Copy link

osmancakir commented Jun 11, 2018

I am also having this 'Error loading Dependencies' problem as @popohoma. Aprreciate the effort loved your conditional formatting!

Edit : after retrying to install

pip install dash-core-components==0.16.0rc1
pip install dash-html-components==0.9.0rc1
pip install dash-renderer==0.13.0rc2
pip install dash-table-experiments==0.6.0rc1

it worked!

@marknuzz
Copy link

It seems like this feature is going to take a very long time. I need to have a straightforward way to detect a click or selection of a cell. Very simple. But I came across this post, which suggests that this feature needs to be done first? https://community.plot.ly/t/dash-datatable-support-for-click-events/7878

I'm open to any workarounds, suggestions, other Dash components, jQuery hacks, anything. But I think users should have the option to interact with a table.

@Tasselmi
Copy link

Tasselmi commented Jul 23, 2018

I have some problems in running the code above.
THE code error is : "error loading layout".
THERE is something wrong with your code .
BUT i am new , i do not know where is wrong, crying......

@bcliang
Copy link

bcliang commented Aug 8, 2018

@Mnuzz once this feature is merged you'll be able to insert components (dcc, html) into each table cell. That means, for example, that navigation cells could be made using a component of type html.A and "clickable" cells could be made of the html.Button component.

something like the following ..

def prep_dataframe_for_datatable(dataframe):
    rows = []
    for i in range(len(dataframe)):
        row = dataframe.iloc[i].to_dict()
        row['Link'] = html.A('Link', href='/route/to/{}'.format(row['href'])) # assume there is a dataframe column named href
        rows.append(row)
    return rows

The recommendation was to use the class html.Button, which would require you to dynamically handle callbacks for the buttons. If html.A or dcc.Link would suffice that might be easier.

If you need this feature urgently, you could use the code from this PR directly. Just follow the pip install ... for the code versions listed above.

@marknuzz
Copy link

marknuzz commented Aug 8, 2018

@bcliang You miss the point. This is essentially a major revision release, containing a very large amount of changes. My point was that there are common use cases which are not covered, such as selecting a row from a list. Very common use case. However, users are expected to wait for this major revision, which a large set of complex changes, many of which are out of scope for what most users are looking to do.

Sure, you could cover this common use case after the release. But this PR has been up for 10 months. I understand that it's a complex issue. But to put on indefinite hold, the fixes to address common use cases, especially if they are likely straightforward to implement in the current framework, is not something I understand.

I'm not even asking the dev team to implement the said fix. It's one thing to ask a user to submit a PR (and perhaps spending a couple extra minutes explaining the gist of how to implement a new event). It's an entirely different thing to tell the user "You'll have to wait until this 10 month PR is accepted. We don't know when it will be accepted, but sorry, you'll have to wait. But hey, you're welcome to use the unmerged code in the meantime!"

@chriddyp
Copy link
Member Author

chriddyp commented Aug 9, 2018

"You'll have to wait until this 10 month PR is accepted. We don't know when it will be accepted, but sorry, you'll have to wait. But hey, you're welcome to use the unmerged code in the meantime!"

I'm sorry there has been confusion with these types of prereleases. They are really targeted towards other Dash developers and serve as a way to get feedback about future, prototypical architectures. It's a way for us to explore the boundaries of Dash and to do so in a way that other community members can provide feedback on.

We're split our time about 70%-30% between engineering that has short-term improvements (see https://github.com/orgs/plotly/projects) and projects that are more theoretical and exploratory and push the boundaries of Dash and inform what Dash 2.0 would look like (like this original PR).

This PR likely won't actually get merged anytime soon, but it did a lot to inform me on some different possibilities and what community members would like out of a feature like this. Many aspects of this feedback has been incorporated into a new version of an interactive table component which we have been writing from scratch. These features include dropdowns inside cells, single and multi row selections, conditional formatting, cell and column formatting, data types in the table, and more. Thanks to some organizations that have sponsored the work, we are looking to release this towards the end of the month.

Again, I'm sorry to get people's hopes up by sharing these prototypes through exploratory pull requests like these. I'll try to do a better job in the feature of declaring up-front whether a PR is a candidate for immediate release or whether it is a candidate for feedback and discovery. In both cases, the community's feedback has been very helpful, and I really appreciate it. ❤️

@marknuzz
Copy link

marknuzz commented Aug 9, 2018

Thanks @chriddyp that makes sense.

@Harsha-Nori
Copy link

Thanks for all your hard work @chriddyp! Will the upcoming interactive table component support sparklines to some degree (plotly graphs within cells)?

@AsmitAdgaonkar
Copy link

Thanks @chriddyp and team. Do we know if conditional formatting is released/merged yet ?

I am currently on
dash 0.28.1
dash-core-components 0.30.2
dash-html-components 0.13.2
dash-renderer 0.14.1
dash-table-experiments 0.6.0

Let me know if you suggest a minor change/pull in any of the libraries to accommodate background color for dash datatable ?

@alexcjohnson
Copy link
Collaborator

Closing as this repo is deprecated in favor of dash-table. This feature still requires work on the dash-renderer side, but from the table side you can follow progress at eg plotly/dash-table#292, plotly/dash-table#222

@alexcjohnson alexcjohnson deleted the sub-renderer branch May 28, 2019 18:56
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Href links as values?