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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP - enable components as cells #11

Open
wants to merge 2 commits into
base: master
from

Conversation

Projects
None yet
@chriddyp
Member

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

This comment has been minimized.

richard-muir commented Oct 18, 2017

Yes! This looks incredible :-)

@chriddyp chriddyp changed the title from enable components as cells to WIP - enable components as cells Oct 23, 2017

@BAjayiobe1

This comment has been minimized.

BAjayiobe1 commented Nov 7, 2017

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

@jdagdelen

This comment has been minimized.

jdagdelen commented Dec 5, 2017

I heartily support this feature as well.

@gustavengstrom

This comment has been minimized.

gustavengstrom commented Dec 14, 2017

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

This comment has been minimized.

Member

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

This comment has been minimized.

gustavengstrom commented Dec 14, 2017

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

This comment has been minimized.

Member

chriddyp commented Dec 15, 2017

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

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

@chriddyp

This comment has been minimized.

Member

chriddyp commented Dec 15, 2017

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

This comment has been minimized.

Member

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

This comment has been minimized.

Member

chriddyp commented Dec 18, 2017

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

This comment has been minimized.

gustavengstrom commented Dec 20, 2017

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

This comment has been minimized.

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/dash-table-experiments@0.6.0rc1/dash_table_experiments/dash_table_experiments.css

@chriddyp

This comment has been minimized.

Member

chriddyp commented Dec 22, 2017

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

This comment has been minimized.

annitrolla commented Jan 15, 2018

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

This comment has been minimized.

Member

chriddyp commented Jan 15, 2018

@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

This comment has been minimized.

annitrolla commented Jan 16, 2018

@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

This comment has been minimized.

gustavengstrom commented Jan 27, 2018

@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

This comment has been minimized.

mankensin commented Feb 20, 2018

@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

This comment has been minimized.

Member

chriddyp commented Feb 20, 2018

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

This comment has been minimized.

mankensin commented Feb 20, 2018

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

@mankensin

This comment has been minimized.

mankensin commented Feb 23, 2018

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

@mankensin

This comment has been minimized.

mankensin commented Feb 23, 2018

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

This comment has been minimized.

Member

chriddyp commented Feb 23, 2018

@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

This comment has been minimized.

FarrandTom commented Feb 26, 2018

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

This comment has been minimized.

Member

chriddyp commented Feb 26, 2018

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

This comment has been minimized.

FarrandTom commented Mar 1, 2018

@pbosavage

This comment has been minimized.

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/dash-table-experiments@0.6.0rc1/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

This comment has been minimized.

Member

rmarren1 commented Apr 25, 2018

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

@Pastryman

This comment has been minimized.

Pastryman commented May 8, 2018

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

This comment has been minimized.

udhayasankari commented May 14, 2018

@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

This comment has been minimized.

nevenpiculjan commented May 17, 2018

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

This comment has been minimized.

popohoma commented May 20, 2018

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

This comment has been minimized.

northcuttc52 commented Jun 7, 2018

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

This comment has been minimized.

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!

@Mnuzz

This comment has been minimized.

Mnuzz commented Jul 22, 2018

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

This comment has been minimized.

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

This comment has been minimized.

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.

@Mnuzz

This comment has been minimized.

Mnuzz 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

This comment has been minimized.

Member

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. 鉂わ笍

@Mnuzz

This comment has been minimized.

Mnuzz commented Aug 9, 2018

Thanks @chriddyp that makes sense.

@Harsha-Nori

This comment has been minimized.

Harsha-Nori commented Aug 24, 2018

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

@AsmitAdgaonkar

This comment has been minimized.

AsmitAdgaonkar commented Oct 2, 2018

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 ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment