Hello
I have an app that is composed like this
app.layout (Div id=“layout”)
→ config_name (dcc.Input id=“config_name”)
→ tab (3 pages)
→ div 1 (tab1)
–>/ → obj1 (id =“obj1”)
→ div 2 (tab 2)
–>/ → obj2 (id =“obj2” )
→ div 3 (tab 3)
I have stored an object in app.server.shared and i want that all my objects depends on this object
i created two others callbacks firing with obj1 and obj2 modification
i created a callback with the input id=“config_name” and output id=“layout”
this callback return the same list of objects with correspondig ids but dont touch the callbacks
It seems not to work. Is it possible to change the children of a div in a callback ?
even if those children contains components corresponding to callbacks
Im not sure to be clear .
But if it is, and if i am wrong What is the good way to do .
is it better to change only simple objects with a callback ?
I know that it is ridiculous to do that so . But dont pay attention. Should this be working. ?
In another way it is possible to define the layout in a function depending on what i read in a database. if my object change a field , i dnt want to change only the field , i want to reload all the layout containing all the fields
. I think i understand.
Instead of changing all the layout . you can change a part of the layout using Patch(). The Patch contains a list and you insert an element only in the place where you want to change a value
Patch() is not a list. It could be something else depending on your component and property you might want to change. Have a read here:
You could do the same thing as I did before but using State(). This would increase data transfer between server and client but might be neglectable in your case.
Anyways, I have the feeling that you actually are looking for pattern matching callbacks by your descriptions of updating only specific components within your layout depending on a given selection and/or condition.
To be more explicit: i m trying to do an app working with a database.
the user can edit configurations and test it .
the general window has a tabs object with 3 div (basculate to 3 different screens)
first div: edition of the configuration that is edited
second div: test of the edited configuration
third div : a table with the list of the user’s configurations
in this table , each row except the row concerning the configuration that is edited has a button “edit” . On clicking on this button , i want that all the information in the first and second div basculate to the clicked configuration , and i want that my table is reorganized to put the button “edit” only in the rows concerning configurations that are not in edition.
i defined 10 callbacks for this table (max 10 configurations) , one for each row . I use a patch object to change my layout.
Each time i return a patch object to my layout , application fires 2 times or more the callback for each button even there is no change. It seems that the layout return operation fires every callback of the appplication concerned by every input object that is inside the layout.
i use the prevent_initial_call=True . but this do its job only in the beginning of app running.
It is difficult to find a solution to inhibate callbacks during this operation of changing of configuration
Hey @Angelo28300, it’s difficult to tell without seeing your code. If you’re able to share utter, I’m sure we can help you. If not, try creating a minimal example which reproduces the issue
Yes !!!
I resolved the bug
I understood how to do .
I stored the value of the config_id of the config that in edition state in a dcc.store object in the most high level of the layout . I created a callback that fires when this value change, and that change all the pages concerned. It works because this dcc.store element is not modified when this callback fires.
I just need to change the value of this dcc.store what ever where i am and it works.
AIMPED maybe you were paying attention on my bug and maybe you sent me good thelepatic vides during the time that i was washing the disches . I had the idea at this moment.
But surely, your questions gave me a way to find the solution . Thanks a lot to you!
To be more clear on the solution
see the next code
from dash import Dash, html, Input, Output,State
app = Dash()
nb_buttons= 3
def under_layout(value):
ulayout = html.Div(
id="layout" ,
children = [
html.Div(f"This Div change. The value is :"),
html.Div(id = "value", children = value)
]
)
for i in range(nb_buttons):
ulayout.children.append(html.Button(id=f"btn{i+1}", children="+1"))
return ulayout
for i in range(nb_buttons):
@app.callback(
Output("layout", "children",allow_duplicate=True),
State("layout", "children"),
State("value", "children"),
Input(f"btn{i+1}", "n_clicks"),
prevent_initial_call=True
)
def update(lay,val,clicks):
if clicks is None:
return lay
else :
return under_layout(val+1)
if __name__ == "__main__":
app.layout = html.Div(children =[
html.Div("This Div doesnt change"),
under_layout(0)]
)
app.run(debug=True)
If tested it , and it works fine
I use the debugger and place a breakpoint in “update” function. I observed that the “update” function fires ony one time when i click .
if I change the number of buttons , for example 100 buttons , I observe that the function ‘update’ is firing 3 times instead of one .
My big code was more complex a observed that a callback can be fired much much lot of times .
I think that this caused by reentrance because the element that fires the callback is changed by itself directly.
So what should be done is something like this :
see the next code
from dash import Dash, html, Input, Output,State,dcc
app = Dash()
nb_buttons= 100
def under_layout(value):
ulayout = html.Div(
id="under_layout" ,
children = [
html.Div(f"This Div change. The value is :"),
html.Div(id = "value", children = value)
]
)
for i in range(nb_buttons):
ulayout.children.append(html.Button(id=f"btn{i+1}", children="+1"))
return ulayout
for i in range(nb_buttons):
@app.callback(
Output("over_value", "data",allow_duplicate=True),
State("value", "children"),
Input(f"btn{i+1}", "n_clicks"),
prevent_initial_call=True
)
def update(val,clicks):
if clicks is None:
return val
else :
return val+1
if __name__ == "__main__":
app.layout = html.Div(
children =[
dcc.Store(id = "over_value", data=0),
html.Div("This Div doesnt change"),
html.Div(id= "under_layout",children=under_layout(0))
]
)
@app.callback(
Output("under_layout","children"),
Input("over_value","data")
)
def change_layout(val):
return under_layout(val)
app.run(debug=True)
In this code , you can see that the buttons change a value that is over the layout that is changed .
So in my case , i find that it is a better way to change the layout because the calling element is outside the under_layout that is changed.
And it is what i tried in my code and it works much better .
Any idea on this specific case ?
Are you finding this is still problematic? Your code here (once a small duplicate ID issue is fixed) works for me, though I’ve seen the odd indication of intermittent issues when running with debug=True.
This whole approach, of dynamically recreating a layout that contains a large number of elements which trigger a large number of callbacks when the content is regenerated, is probably not the most elegant. One relatively straightforward change, that might improve it a little, is to replace the 100 callbacks with a single pattern-matching callback and to raise PreventUpdate when no change is needed (see code below). But I generally agree with @AIMPED that it would be better to find an approach that makes small changes to the layout, rather than completely regenerating a complex layout whenever a button is clicked.
from dash import Dash, html, Input, Output,State,dcc, ALL
from dash.exceptions import PreventUpdate
app = Dash()
nb_buttons= 100
def under_layout(value):
ulayout = html.Div(
id="under_layout0" ,
children = [
html.Div(f"This Div change. The value is :"),
html.Div(id = "value", children = value)
]
)
for i in range(nb_buttons):
ulayout.children.append(html.Button(id={"type":"addbutton","member":i}, children="+1"))
return ulayout
app.layout = html.Div(
children =[
dcc.Store(id = "over_value", data=0),
html.Div("This Div doesnt change"),
html.Div(id= "under_layout",children=under_layout(0))
]
)
@app.callback(
Output("over_value", "data",allow_duplicate=True),
State("value", "children"),
Input({"type":"addbutton","member":ALL}, "n_clicks"),
prevent_initial_call=True
)
def update(val,clicks):
if clicks is None:
raise PreventUpdate
else :
return val+1
@app.callback(
Output("under_layout","children"),
Input("over_value","data")
)
def change_layout(val):
return under_layout(val)
if __name__ == "__main__":
app.run(debug=False)
Thanks a lot David. I did’nt know that is was possible to do it so .
For me :2 lessons
use of PreventUpdate. I have read about that but i didn’t understand really his application
use of one callback instead of 100 with the input({“type”:“addbutton”,“member”:ALL}, “n_clicks”),
This use of a dict instead of multiple id is very interesting . I didnt find a tutorial for this use . But i m still looking for
Hey misters ! Thank a lot for the rigth link and for examples. Those features are very useful . I need more some practice and i will be more free in what i can design .