Open jrkkfst opened 3 years ago
What version are you on? Could you share the line where you construct the transform?
I'm on 0.0.53.
app = DashProxy(
transforms=[
MultiplexerTransform(proxy_location=None),
NoOutputTransform(),
],
)
It's for saving data in a dcc.Store and then retrieving it. And i Have multiple callbacks accessing the State of the Store object and then Also as Output.
I tried different thing with dcc.Store or just using a hidden html
It's a little complex because I have a class which creates the html objects and callbacks on launch, and then I create multiple objects of that class.
I am adding the callback without the decorator directly by calling app.callback, it hasn't worked with the decorator function.
Some code snippets:
This is the html object where I initialise the children as None. It is here I would expect if I didn't initialize it may cause error, but I set it.
html.Div(None, id=f"{
self.id}_storage", style={"display": "none"})
How I create the callbacks
callback = self.make_callback(
# function that returns the appropriate callback function
)
app.callback(
Output(f"{self.id}_storage", "children"),
[
State(f"{self.id}_storage", "children"),
],
prevent_initial_call=True,
)(callback)
I also faced this error. Can we have multiple dashh_extensions.enrich.Outputs in callbacks?
@jv1522 yes that should be possible
The error seems to indicate that the layout is not defined at the time where the multiplexer is called. I am not really sure how this can happen, but if you can share a reproducible example, I can try to address the problem. Until then, a possible workaround could be to "manually" place the proxy components in the layout, i.e.
proxy_container = html.Div()
app = DashProxy(transforms=[MultiplexerTransform(proxy_location=proxy_container)])
and then making sure that the proxy_container is added to the layout,
app.layout = html.Div([..., proxy_container])
Can we have dash extension's output and the plain dash's Output in the same callback, here is the code example In the below the duplicate_id is being used in another callback with dash extensions' Output
from dash.dependencies import Output
from dash_extensions.enrich import Output as Extended_Output
@app.callback(
Output("unique_id1", "children"),
Output("unique_id2", "data"),
Extended_Output("duplicate_id", "children"),
Input("id1", "value")
)
def do_something():
pass
I am not sure I understand why you don't just use the Output
from dash_extensions.enrich for all the outputs? That would seem simpler
The error seems to indicate that the layout is not defined at the time where the multiplexer is called. I am not really sure how this can happen, but if you can share a reproducible example, I can try to address the problem. Until then, a possible workaround could be to "manually" place the proxy components in the layout, i.e.
proxy_container = html.Div() app = DashProxy(transforms=[MultiplexerTransform(proxy_location=proxy_container)])
and then making sure that the proxy_container is added to the layout,
app.layout = html.Div([..., proxy_container])
I still can't get it to work. I'm sorry I cannot easily provide a minimal working example.
It seems the proxy_container is not correctly populated even when I follow your example. First I initialize the app, then using my class create a number of objects with both html components and their callbacks, then I add those html components to my app.layout. It seems somehow the proxy_container isn't populated correctly.
Do I need to use the: from dash_extensions.enrich import Output ?
I think one key is that I define the proxy_container in the start, and then I create my objects using the classes I have, which makes the html components and callsback. At some point here the proxy_container should modified, and that modified proxy_container has to be fed into the final app.layout, as you suggest. However, because I'm using multiple python files, it is not obvious for me how to do the import of it back and forth to ensure, I then use the final version of the proxy_container.
A key problem could be that I use a class to generate multiple different objects and then I assume that each of the instances of these objects may have added snippets to the proxy_container, and I'm not "saving" all those changes to the proxy_container and adding them "on top of" one another.
any news on this? I have the same behavior. Also for me it is very hard if not impossible to provide a minimal working example. I'm also adding the app.layout inside a class in another file as my DashProxy declaration. My callbacks are also spread across a lot of python files. unfortunately the error traceback doesn't provide help
TypeError: Cannot read properties of undefined (reading 'value')
at handleClientside (webpack://dash_renderer/./src/actions/callbacks.ts?:234:54)
at _callee$ (webpack://dash_renderer/./src/actions/callbacks.ts?:488:25)
at c (http://127.0.0.1:8050/_dash-component-suites/dash/dcc/async-slider.js:1:109231)
at Generator._invoke (http://127.0.0.1:8050/_dash-component-suites/dash/dcc/async-slider.js:1:109019)
at Generator.next (http://127.0.0.1:8050/_dash-component-suites/dash/dcc/async-slider.js:1:109656)
at asyncGeneratorStep (webpack://dash_renderer/./src/actions/callbacks.ts?:37:103)
at _next (webpack://dash_renderer/./src/actions/callbacks.ts?:39:194)
at eval (webpack://dash_renderer/./src/actions/callbacks.ts?:39:364)
at new Promise (<anonymous>)
at eval (webpack://dash_renderer/./src/actions/callbacks.ts?:39:97)
The structure in terms of files shouldn't matter. But if you do some kind of dynamic modification of the app layout post load, it might. I don't see anything in the error message that seems to relate to the MultiplexerTransform
, so I don't really have anything to go on in terms of debugging the issue.
If you can post a minimal example demonstrating the error, I can take a look.
The problem still remains for me and I have to solve it in the future. It is still complex to make a simple minimal working example, but it seems that one of us may have to create one soon.
Yes same here, I cannot get my dash up running with creating those Store-trigger chains manually myself. When creating generic callbacks like in a loop, it scales quite dramatically :D I'll start to think about how to create a minimal example and post it soon
For my, the problem is component specific. Does the following example also through an error for you?
It does for me, if the target component is a dcc.Dropdown
, targeting its value
.
from dash_extensions.enrich import MultiplexerTransform, DashProxy
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output
from dash import html
from dash import dcc
app = DashProxy(__name__,
transforms=[MultiplexerTransform()])
app.layout = \
html.Div([
dcc.Dropdown('dropdown-target', options=[{'label': 'option 1', 'value': 'option 1'},
{'label': 'option 2', 'value': 'option 2'}]),
dbc.Button('Fire callback 1', id='btn-fire-callback-1'),
dbc.Button('Fire callback 2', id='btn-fire-callback-2')
])
@app.callback(Output('dropdown-target', 'value'),
Input('btn-fire-callback-1', 'n_clicks'), prevent_initial_call=True)
def _fire_callback_1(n):
if n:
return 'option 1'
@app.callback(Output('dropdown-target', 'value'),
Input('btn-fire-callback-2', 'n_clicks'), prevent_initial_call=True)
def _fire_callback_1(n):
if n:
return 'option 2'
if __name__ == '__main__':
app.run_server(debug=True)
using: dash 2.0.0 das-extensions 0.0.65 dash-bootstrap-components 1.0.1
No, the example works for me. I just tried creating a new venv from scratch installing only the packages you listed. For reference, I am OSX using Python 3.9.1
I use python 3.7.8 on Ubuntu 20.04. and anaconda 4.9.2
Could you try with 3.9? And maybe without anaconda (I doubt it's related, but I don't use it)? (just the small example, so that we can locate the origin of the error)? Altså, I am testing with Chrome browser.
yep, my minimal example for me works on python 3.9.1 (on a fresh anaconda env with just the needed packages). I'll confirm again, if this also works with my full dash app
Great. Let me know how it goes. If it works out, I'll add a note in the docs that Python 3.9 is recommended.
Now it 'sort of works'. However, it feels very unstable. Here's why:
Before I heard about your MultiplexerTransform
, I used to solve multiple outputs for components just like you did it in your extension: with chains of triggers 'funneling' many callbacks to one output. All manually. Now, whenever I 'free' one of those trigger funnels and 'release' two or more callbacks to output to the same component, I end up with the same error, I posted earlier. I can resolve it when I stop the dash app, clean my browser's cache and restart the app again. Hence dash loses its ability to hot-reload after changes which is quite annoying and doesn't feel save to be honest. Is this behavior expected or something that is easy to explain?
It don't see why it should be be necessary to clear any cache. But if you do any modifications that change the component structure of the app, you might need to do a full refresh (e.g. app restart + browser reload, i.e. F5 or so) of the app to ensure that the auto generated multiplexing elements are created properly. I haven't worked much with hot reload, so I am not sure how well it integrates.
In terms of "feeling safe", I would generally think that using a standardised implementation (like the one here) would be less error prone (and easier to maintain) as compared to manually implementing the logic each time. I am not saying it's error free, but I (and others) have used it across a number of apps without issues.
It don't see why it should be be necessary to clear any cache. But if you do any modifications that change the component structure of the app, you might need to do a full refresh (e.g. app restart + browser reload, i.e. F5 or so) of the app to ensure that the auto generated multiplexing elements are created properly. I haven't worked much with hot reload, so I am not sure how well it integrates.
Yes the hot reloading does not integrate fully. The only difference between the behavior of Dash
and DashProxy
is the following:
Like I stated before, my app has loads of self made trigger chains that I now 'free' one-by-one using your extension. Every time I do so, I need to restart the page (even if app.run_server(debug=True
) is set) to get the changes applied. Otherwise I get the error message, posted earlier. The hot reloading itself works. When I change anything that does not regard the functionality of MultiplexerTransform
, changes in the layout or with callbacks are accepted right away. Maybe this helps if you are keen to trace this down. I'd be happy to help you with that, if you can think of any more information that you might need.
In terms of "feeling safe", I would generally think that using a standardised implementation (like the one here) would be less error prone (and easier to maintain) as compared to manually implementing the logic each time. I am not saying it's error free, but I (and others) have used it across a number of apps without issues.
99% agree. The only thing that is annoying, is that one does not get any useful information from error messages that simply say that "something went wrong in the JS backend". That being said: Thanks heaps for your effort in creating this extension and the instant support!
I keep getting the error
Cannot read property 'children' of undefined when applying the MultiplexerTransform extension.
Unfortunately I cannot share a reproducible example at this time. I have tried creating the objects with defined children.
Any ideas of where to begin addressing this?