# Please help me with my extendData callback

**URL:** <https://community.plotly.com/t/please-help-me-with-my-extenddata-callback/61484>\
**Category:** Dash Python\
**Created:** [February 28, 2022, 11:41am UTC](https://community.plotly.com/t/please-help-me-with-my-extenddata-callback/61484 "2022-02-28T11:41:54Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![hmiemad](https://avatars.discourse-cdn.com/v4/letter/h/9de0a6/32.png) [@hmiemad](https://community.plotly.com/u/hmiemad)\
**Post date:** [February 28, 2022, 11:41am UTC](https://community.plotly.com/t/please-help-me-with-my-extenddata-callback/61484/1 "2022-02-28T11:41:54Z")

</div>

I have a graph that I update in 2 manners :

- When I press on the save button : the whole content is updated, I send a request back to the server, then the server asks the backend for data crunching and analysis, send back dictionaries to the front server, updates the content and does some other bunch of things (updating inner custom objects). In this callback, I update the “figure”. My figure is in two parts : a heavy scatter in the background and 6 very light line traces on top. I call a first file that loads my Scatter, this file calls a second file that loads the lines. I separated the lines in a second file for the next purpose. THIS WORKS FINE.

```auto
    @app.callback(
        Output("P_T", "figure"),
        Output("heatmap", "figure"),
        Output("ts","figure"),
        Input('test-params', 'n_clicks'),
        Input('save-params', 'n_clicks'),
        [State(parameter["input"], "value") for parameter in app.structure["FLAT"].values() if parameter["type"] != "time"])
    def update_graph(click_test,click_save, *parameters):
        return [
            scatter_power_temp(app.data["df"], *parameters), # this is the dcc.Graph I'm worried about
            heatmap(app.data["df"].temperature.values,app.data["df"].unexplained.values),
            plot_ts_full(app.data["df"]),
            ]

```

Initialization goes fine, my scatter shows, the default lines show (0 all over as intended). The following is the end of scatter\_power\_temp

```auto
    fig = go.Figure(data=data,layout=layout)

    traces=params_to_traces(*parameters)[0]

    for i in range(6):
        x=traces["x"][i]
        y=traces["y"][i]
        model_i=go.Scatter(x=x,y=y)
        fig.add_trace(model_i)

    return fig

```

and now the return of params\_to\_traces :

```auto
    return dict(x=x,y=y),[1,2,3,4,5,6],7

```

Again, this works fine :  
 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/f/6/f686724670eb15a1fe3195dc8a497cafd3c047d3.png)

As you can see in the first callback, there are a bunch of parameters that will be converted to the 6 lines from params\_to\_traces. I want to make a clientside callback that instantly updates my 6 lines when someone changes one parameter, by using extendData. So I switch from State to Input on those parameters, and from “figure” to “extendData” and only call my params\_to\_traces. Also, I keep my first callback for general and obvious updating purposes of a Save button. But before I go on include a js file, I’m trying with the classic callback in python language.

```auto
    @app.callback(
        Output("P_T", "extendData"),
        [Input(parameter["input"], "value") for parameter in app.structure["FLAT"].values() if parameter["type"] != "time"])
    def extend_traces(*parameters):
        traces=params_to_traces(*parameters)
        print(traces)
        return traces

```

The traces don’t show, instead I have an empty dcc.Graph. The print statement gives :

```auto
({'x': [[-10, 5, 10, 15, 20, 30, 40], [-10, 5, 10, 15, 20, 30, 40], [-10, 5, 10, 15, 20, 30, 40], [-10, 5, 10, 15, 20, 30, 40], [-10, 5, 10, 15, 20, 30, 40], [-10, 5, 10, 15, 20, 30, 40]], 'y': [[0.0, 0.0, 0.0, 0, 
0, 0, 0], [0.0, 0.0, 0.0, 0, 0, 0, 0], [0.0, 0.0, 0.0, 0, 0, 0, 0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]}, [1, 2, 3, 4, 5, 6], 7)

```

EDIT : I went on and wrote the javascript, the clientside\_callback is the following :

```auto

    app.clientside_callback(
        """
        function params_to_traces( lo_slope, up_slope, T_pivot, P_pivot, partial_power, full_power, heating_power, sat_heat, set_heat, cooling_power, set_cool, sat_cool){

            const temp=[-10,40,T_pivot,sat_heat,set_heat,sat_cool,set_cool];
            temp.sort();
            const refrigeration_powers = new Array(temp.length);
            const partial_lighting = new Array(temp.length);
            const full_lighting = new Array(temp.length);
            const hvac_powers = new Array(temp.length);
            const x = new Array(6);
            const y = new Array(6);
            
            for (let i = 0; i < 6; i++) {
                x[i] = new Array(temp.length).fill(0);
                y[i] = new Array(temp.length).fill(0);
            }
            for (let j = 0; j < temp.length; j++) {
                refrigeration_powers[j] = P_pivot + (temp[j] - T_pivot) * lo_slope + Math.max(0.0, temp[j] - T_pivot) * up_slope;
                partial_lighting[j] = partial_power;
                full_lighting[j] = full_power;
                hvac_powers[j] = heating_power * Math.min(1.0, Math.max(0.0, (temp[j] - sat_heat) / (set_heat - sat_heat)))
                            + cooling_power * Math.min(1.0, Math.max(0.0, (temp[j] - sat_cool) / (set_cool - sat_cool)));

                for (let i = 0; i < 6; i++){
                    x[i][j] = temp[j];
                }
                y[0][j] = refrigeration_powers[j];
                y[1][j] = refrigeration_powers[j] + partial_lighting[j];
                y[2][j] = refrigeration_powers[j] + partial_lighting[j] + full_lighting[j];
                y[3][j] = refrigeration_powers[j] + hvac_powers[j];
                y[4][j] = refrigeration_powers[j] + partial_lighting[j] + hvac_powers[j];
                y[5][j] = refrigeration_powers[j] + partial_lighting[j] + full_lighting[j] + hvac_powers[j];
            }
            return [{x:x,y:y},[1,2,3,4,5,6],7]
        }

        """,
        Output(Power_vs_Temperature, "extendData"),
        [Input(parameter["input"], "value") for parameter in app.structure["FLAT"].values() if parameter["type"] != "time"],
    )

```

About the Input array, I put some of the dash components in a dict in the app, this way I can have access to them in any python file and that let’s me rearrange and split my code in files and folders in a manner similar to my dash app layout. I wish there was something like a callbacks.init\_app(dash\_app) possibility, without having to import third party libraries with 1 or 2 stars, but in the meantime I use this architecture, and it works.

Except for this extendData stuff.

---

<div class="post-metadata">

**Author:** ![jlfsjunior](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jlfsjunior/32/16061_2.png) [@jlfsjunior](https://community.plotly.com/u/jlfsjunior)\
**Post date:** [March 1, 2022, 5:15pm UTC](https://community.plotly.com/t/please-help-me-with-my-extenddata-callback/61484/2 "2022-03-01T17:15:32Z")

</div>

Hi,

Your `extendData` looks as it should, but I am wondering if the callback is not getting triggered before the figure is generated by the first callback…  
You can try to add a `prevent_initial_update` on the extend\_traces callback to see if this fixes the problem (or perhaps check for an empty figure, by passing `State("P_T", "figure")`.

Let me know if this helps! 🙂

---

<div class="post-metadata">

**Author:** ![hmiemad](https://avatars.discourse-cdn.com/v4/letter/h/9de0a6/32.png) [@hmiemad](https://community.plotly.com/u/hmiemad)\
**Post date:** [March 2, 2022, 12:58pm UTC](https://community.plotly.com/t/please-help-me-with-my-extenddata-callback/61484/3 "2022-03-02T12:58:35Z")

</div>

Hi,

Thanks for the reply.  
Following your advice, I tried both `prevent_initial_update` and `prevent_initial_call`, but it still doesn’t work.  
The two callbacks follow each other in the code :

 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/a/f/af688ce0a959048ee2fd2610ea3426788100a13b.png)

the hide\_client\_side\_ is just a trick to hide commented code on VSCode, it’s my js code. The dcc.Graph are declared above.

The thing is that I create the components and the callbacks inside a function that has app as a parameter. I create the components, I add the callbacks, then I load the components into the layout via the return. So technically, I create the callbacks before the components are loaded.

```auto
from dash import dcc,html

from .content_site import content_site
from .content_phase import content_phase
from .content_model import content_model

CONTENT_STYLE = {
    "margin-left": "18rem",
    "margin-right": "2rem",
    "padding": "2rem 1rem",
}

def content(app):
    app.content_site=content_site(app)
    app.content_phase=content_phase(app)
    app.content_model=content_model(app)
    return html.Div(
        id="content",
        children=[app.content_site,app.content_phase,app.content_model],
        className="col-9",
    )

```

But this works for the rest of the code. I believe that the components don’t even have to be loaded (for instance a heavy dcc.store, hidden in the server side), for the callbacks to trigger.

Are there good practices for declaring callbacks in a non linear file structure?

---

<div class="post-metadata">

**Author:** ![hmiemad](https://avatars.discourse-cdn.com/v4/letter/h/9de0a6/32.png) [@hmiemad](https://community.plotly.com/u/hmiemad)\
**Post date:** [March 4, 2022, 5:41pm UTC](https://community.plotly.com/t/please-help-me-with-my-extenddata-callback/61484/4 "2022-03-04T17:41:24Z")

</div>

I got it to work.  
Two things I learned doing this :

- load the whole layout before adding callbacks, and I found [this thread](https://community.plotly.com/t/splitting-callback-definitions-in-multiple-files/10583) helpful.
- for loops to add callbacks DO NOT WORK if the first attribute given to Input, Output or State is a component. You need the id string to be passed. Which is kind of easy, you just add `.id` to the component, but then I don’t know if you need to define the id when you instantiate the component, or if the automatic id generator of the constructor is enough. Even more so if you use clientside callbacks, make sure you enter the ID.

---

<div class="post-metadata">

**Author:** ![randrew](https://avatars.discourse-cdn.com/v4/letter/r/7cd45c/32.png) [@randrew](https://community.plotly.com/u/randrew)\
**Post date:** [July 4, 2023, 6:25pm UTC](https://community.plotly.com/t/please-help-me-with-my-extenddata-callback/61484/5 "2023-07-04T18:25:25Z")

</div>

It’s nice that you have found the solution for your question. But could you explain in more detail what you have done? I’m going to post a question on the same topic and it would be great if you help me…
