Callback not trigger

Hi, i’m trying to make a dash app with multiples grids.

Each grid will do the same thing and should trigger identicals callbacks

This is the code:

from dash import Dash, html, Input, Output
import dash_html_components as html
import dash_mantine_components as dmc
import dash_bootstrap_components as dbc
from dash_iconify import DashIconify
import pandas as pd

app = Dash(__name__,
                  external_stylesheets=[dbc.themes.FLATLY, 'https://fonts.googleapis.com/css?family=Poppins'], 
                  suppress_callback_exceptions=True,
                  meta_tags=[{'name': 'viewport','content': 'width=device-width, initial-scale=1.0'}],
                  update_title='Atualizando ...')

select_classnames = {'input': 'input-custom', 'item': 'item-custom', 'rightSection': 'rightSection-custom'}

icons_date = "clarity:date-line"
icons_vars = "wi:day-cloudy-gusts"
icons_model = "bi:stack"

options_gfs = [
            {"value": 'Acumulado Semanal', "label": 'Acumulado Semanal', "group" : "Precipitação"},
            {"value": 'Prec 24 horas', "label": 'Prec 24 horas', "group" : "Precipitação"},
            {"value": 'Acumulado total de precipitação', "label": 'Acumulado total de precipitação', "group" : "Precipitação"},
            {"value": 'Prec 24 horas e PNMM', "label": 'Prec 24 horas e PNMM', "group" : "Precipitação"},
            {"value": 'Prec 24 horas nos polos de biomassa', "label": 'Prec 24 horas nos polos de biomassa', "group" : "Precipitação"},
            {"value": 'Jato 200hPa', "label": 'Jato e divergência em 200hPa', "group" : "Dinâmica"},
            {"value": 'Vento e temperatura 850hPa', "label": 'Vento e temperatura em 850hPa', "group" : "Dinâmica"},
            {"value": 'Vorticidade e Geopotencial 500hPa', "label": 'Vorticidade e Geopotencial em 500hPa', "group" : "Dinâmica"},
            {"value": 'Vento em 850hPa', "label": 'Vento em 850hPa', "group" : "Dinâmica"},
            {"value": 'Risco de geadas - Mapas', "label": 'Risco de geadas - Mapas', "group" : "Dinâmica"},
            {"value": 'Prec 24 horas por cidade', "label": 'Prec 24 horas por cidade', "group" : "Gráficos"},
            {"value": 'Risco de geadas - Gráficos', "label": 'Risco de geadas - Gráficos', "group" : "Gráficos"},
            {"value": 'Temperatura por cidade', "label": 'Temperatura do ar por cidade', "group" : "Gráficos"},
            {"value": 'Temperatura por submercado', "label": 'Temperatura do ar por submercado', "group" : "Gráficos"},
            {"value": 'Magnitude do vento a 100m', "label": 'Magnitude do vento a 100m', "group" : "Gráficos"},
            {"value": 'Todos os campos', "label": 'Todos os campos', "group" : "Painel"},
        ]

options_ecmwf_gefs_estendido = [
            {"value": 'Acumulado Semanal', "label": 'Acumulado Semanal', "group" : "Precipitação"},
            {"value": 'Anomalia do acumulado semanal', "label": 'Anomalia do acumulado semanal', "group" : "Precipitação"},
            {"value": 'Prec mensal', "label": 'Precipitação mensal', "group" : "Precipitação"},
            {"value": 'Prec 24 horas', "label": 'Prec 24 horas', "group" : "Precipitação"},
        ]

options_tok30 = [
            {"value": 'Acumulado Semanal', "label": 'Acumulado Semanal', "group" : "Precipitação"},
            {"value": 'Prec 24 horas', "label": 'Prec 24 horas', "group" : "Precipitação"},
            {"value": 'Jato 200hPa', "label": 'Jato e divergência em 200hPa', "group" : "Dinâmica"},
            {"value": 'Vento e temperatura 850hPa', "label": 'Vento e temperatura em 850hPa', "group" : "Dinâmica"},
            {"value": 'Vorticidade e Geopotencial 500hPa', "label": 'Vorticidade e Geopotencial em 500hPa', "group" : "Dinâmica"},
            {"value": 'Vento em 850hPa', "label": 'Vento em 850hPa', "group" : "Dinâmica"},
        ]

options_tok10 = [
            {"value": 'Acumulado Semanal', "label": 'Acumulado Semanal', "group" : "Precipitação"},
            {"value": 'Prec 24 horas', "label": 'Prec 24 horas', "group" : "Precipitação"},
            {"value": 'Acumulado total de precipitação', "label": 'Acumulado total de precipitação', "group" : "Precipitação"},
            {"value": 'Jato 200hPa', "label": 'Jato e divergência em 200hPa', "group" : "Dinâmica"},
            {"value": 'Vento e temperatura 850hPa', "label": 'Vento e temperatura em 850hPa', "group" : "Dinâmica"},
            {"value": 'Vorticidade e Geopotencial 500hPa', "label": 'Vorticidade e Geopotencial em 500hPa', "group" : "Dinâmica"},
            {"value": 'Vento em 850hPa', "label": 'Vento em 850hPa', "group" : "Dinâmica"},
        ]

options_eta = [
            {"value": 'Acumulado Semanal', "label": 'Acumulado Semanal', "group" : "Precipitação"},
        ] 

opcoes_gerais = [
            {"value": 'Acumulado Semanal', "label": 'Acumulado Semanal', "group" : "Precipitação"},
            {"value": 'Prec 24 horas', "label": 'Prec 24 horas', "group" : "Precipitação"},
            {"value": 'Acumulado total de precipitação', "label": 'Acumulado total de precipitação', "group" : "Precipitação"},
            {"value": 'Prec 24 horas e PNMM', "label": 'Prec 24 horas e PNMM', "group" : "Precipitação"},
            {"value": 'Jato 200hPa', "label": 'Jato e divergência em 200hPa', "group" : "Dinâmica"},
            {"value": 'Vento e temperatura 850hPa', "label": 'Vento e temperatura em 850hPa', "group" : "Dinâmica"},
            {"value": 'Vorticidade e Geopotencial 500hPa', "label": 'Vorticidade e Geopotencial em 500hPa', "group" : "Dinâmica"},
            {"value": 'Vento em 850hPa', "label": 'Vento em 850hPa', "group" : "Dinâmica"},
            {"value": 'Todos os campos', "label": 'Todos os campos', "group" : "Painel"},
        ]

options_merge = [
            {"value": 'Prec observada 24 horas', "label": 'Prec 24 horas', "group" : "Precipitação"},
        ] 

options_regiao = [
    {"value": 'regiao norte', "label": 'Cidades Norte'},
    {"value": 'regiao centro-oeste', "label": 'Cidades Centro-Oeste'},
    {"value": 'regiao nordeste', "label": 'Cidades Nordeste'},
    {"value": 'regiao sudeste', "label": 'Cidades Sudeste'},
    {"value": 'regiao sul', "label": 'Cidades Sul'},
    ]

def gera_comparacao(n):

    modelos = [
        {"value": 'GFS', "label": 'NCEP-GFS', "group" : "Previsão curto prazo"},
        {"value": 'GEFS', "label": 'NCEP-GEFS', "group" : "Previsão curto prazo"},
        {"value": 'ECMWF', "label": 'ECMWF', "group" : "Previsão curto prazo"},
        {"value": 'ECMWF-ENS', "label": 'ECMWF-ENS', "group" : "Previsão curto prazo"},
        {"value": 'ETA', "label": 'ETA-ONS', "group" : "Previsão curto prazo"},
        {"value": 'TOK10', "label": 'TOK10', "group" : "Previsão curto prazo"},
        {"value": 'TOK30', "label": 'TOK30', "group" : "Previsão curto/médio prazo"},
        {"value": 'ECMWF-ENS-ESTENDIDO', "label": 'ECMWF-ENS-ESTENDIDO', "group" : "Previsão estendida"},
        {"value": 'GEFS-ESTENDIDO', "label": 'GEFS-ESTENDIDO', "group" : "Previsão estendida"},
    ]

    style = {
        "textAlign": "center",
        'margin-top': '5px',
    }

    children1 = dmc.Select(id=f'lista-de-modelos{n}', data=[x for x in modelos], value=modelos[n]['value'], searchable=True, style={"margin": 10}, classNames=select_classnames, icon=DashIconify(icon=icons_model))
    children2 = dmc.Select(id=f'lista-de-datas{n}', style={"margin": 10}, classNames=select_classnames, icon=DashIconify(icon=icons_date))
    children3 = dmc.Select(id=f'lista-de-variaveis{n}', style={"margin": 10}, searchable=True, classNames=select_classnames, icon=DashIconify(icon=icons_vars))
    children4 = html.Div(children=[], id=f'div-figuras{n}', className='comparacaoimagem border-dark shadow-lg p-1 mb-2 bg-white rounded', style={'width': '100%'})

    conteudo_temp = html.Div([
        
        html.Div(children=[children1, children2, children3, children4], style=style)
        
        ])
    
    conteudo = dbc.Container([conteudo_temp], fluid=True, className='main')
    
    @app.callback(
    Output(f'lista-de-datas{n}', 'data'),
    Output(f'lista-de-datas{n}', 'value'),
    Output(f'lista-de-datas{n}', 'disabled'),
    Input(f'lista-de-modelos{n}', 'value')
    )
    def escolhe_data(value):

        if 'MERGE' not in value:

            dirs = ['20231101', '20231102']
            dirs = [pd.to_datetime(x, format='%Y%m%d%H') for x in dirs]
            dirs = sorted(dirs, reverse=True)
            dirs = [x.strftime('%d/%m/%Y %H UTC') for x in dirs]
            dirs = [{'value': x, 'label': x, "group" : pd.to_datetime(x).strftime('%d/%m/%Y')} for x in dirs]

            return dirs, dirs[0]['value'], False

        else:

            ini = ['-']
            variavel = 'Precipitação acumulada em 24 hr'

            return ini, variavel, True
        
    @app.callback(
    Output(f'lista-de-variaveis{n}', 'data'),
    Output(f'lista-de-variaveis{n}', 'value'),
    Input(f'lista-de-modelos{n}', 'value')
    )
    def escolhe_vars(value):

        if value == 'GFS':

            options = options_gfs 

            options = [x for x in options]

        elif value == 'ETA':

            options = options_eta

            options = [x for x in options]

        elif value == 'ECMWF-ENS-ESTENDIDO' or value == 'GEFS-ESTENDIDO':

            options = options_ecmwf_gefs_estendido

            options = [x for x in options]

        elif value == 'TOK30':

            options = options_tok30

        elif value == 'TOK10' or value == 'TOK30':

            options = options_tok10

        elif value == 'MERGEGPM':

            options = options_merge

        else:

            options = opcoes_gerais

            options = [x for x in options]
            
        return options, options[0]['value']

    return conteudo

conteudo = html.Div([

dmc.NumberInput(
    label="Escolha o numero de colunas para comparar",
    id='input-colunas',
    value=3,
    min=3,
    max=5,
    step=1,
    style={"width": 250},
),
html.Div(id='grids')
])

app.layout = conteudo

@app.callback(
Output('grids', 'children'),
Input('input-colunas', 'value')
)
def escolhe_num_cols(cols):

    childrens = []

    for n in range(cols):
        childrens.append(gera_comparacao(n))

    grid = dmc.SimpleGrid(

        cols=cols,
        children=childrens,
        id='grid-comparacao',
    )

    return grid

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

This code works fine updating the numbers of colunms based on a callback “escolhe_num_cols”. However, the callbacks inside “gera_comparacao” function doesn’t.

animação2

The callbacks inside “gera_comparacao” function changes the last row of each column, as follows:

animação1

So the expected is that this callback inside “gera_comparacao” funtion also trigger when the number of columns changes.

Why this happens?

Hi @jp123

Callbacks cannot be created inside other callbacks - all the callbacks must exist before the app starts (more info in the Dash docs. Have you tried pattern matching callbacks?

I’m trying to implement these method, but the second callback continue not trigger …

from dash import Dash, html, Input, Output, Patch, ALL
import dash_html_components as html
import dash_mantine_components as dmc
import dash_bootstrap_components as dbc
from dash_iconify import DashIconify
import pandas as pd

app = Dash(__name__,
                  external_stylesheets=[dbc.themes.FLATLY, 'https://fonts.googleapis.com/css?family=Poppins'], 
                  suppress_callback_exceptions=True,
                  meta_tags=[{'name': 'viewport','content': 'width=device-width, initial-scale=1.0'}],
                  update_title='Atualizando ...')

select_classnames = {'input': 'input-custom', 'item': 'item-custom', 'rightSection': 'rightSection-custom'}

icons_date = "clarity:date-line"
icons_vars = "wi:day-cloudy-gusts"
icons_model = "bi:stack"

options_gfs = [
            {"value": 'Acumulado Semanal', "label": 'Acumulado Semanal', "group" : "Precipitação"},
            {"value": 'Prec 24 horas', "label": 'Prec 24 horas', "group" : "Precipitação"},
            {"value": 'Acumulado total de precipitação', "label": 'Acumulado total de precipitação', "group" : "Precipitação"},
            {"value": 'Prec 24 horas e PNMM', "label": 'Prec 24 horas e PNMM', "group" : "Precipitação"},
            {"value": 'Prec 24 horas nos polos de biomassa', "label": 'Prec 24 horas nos polos de biomassa', "group" : "Precipitação"},
            {"value": 'Jato 200hPa', "label": 'Jato e divergência em 200hPa', "group" : "Dinâmica"},
            {"value": 'Vento e temperatura 850hPa', "label": 'Vento e temperatura em 850hPa', "group" : "Dinâmica"},
            {"value": 'Vorticidade e Geopotencial 500hPa', "label": 'Vorticidade e Geopotencial em 500hPa', "group" : "Dinâmica"},
            {"value": 'Vento em 850hPa', "label": 'Vento em 850hPa', "group" : "Dinâmica"},
            {"value": 'Risco de geadas - Mapas', "label": 'Risco de geadas - Mapas', "group" : "Dinâmica"},
            {"value": 'Prec 24 horas por cidade', "label": 'Prec 24 horas por cidade', "group" : "Gráficos"},
            {"value": 'Risco de geadas - Gráficos', "label": 'Risco de geadas - Gráficos', "group" : "Gráficos"},
            {"value": 'Temperatura por cidade', "label": 'Temperatura do ar por cidade', "group" : "Gráficos"},
            {"value": 'Temperatura por submercado', "label": 'Temperatura do ar por submercado', "group" : "Gráficos"},
            {"value": 'Magnitude do vento a 100m', "label": 'Magnitude do vento a 100m', "group" : "Gráficos"},
            {"value": 'Todos os campos', "label": 'Todos os campos', "group" : "Painel"},
        ]

options_ecmwf_gefs_estendido = [
            {"value": 'Acumulado Semanal', "label": 'Acumulado Semanal', "group" : "Precipitação"},
            {"value": 'Anomalia do acumulado semanal', "label": 'Anomalia do acumulado semanal', "group" : "Precipitação"},
            {"value": 'Prec mensal', "label": 'Precipitação mensal', "group" : "Precipitação"},
            {"value": 'Prec 24 horas', "label": 'Prec 24 horas', "group" : "Precipitação"},
        ]

options_tok30 = [
            {"value": 'Acumulado Semanal', "label": 'Acumulado Semanal', "group" : "Precipitação"},
            {"value": 'Prec 24 horas', "label": 'Prec 24 horas', "group" : "Precipitação"},
            {"value": 'Jato 200hPa', "label": 'Jato e divergência em 200hPa', "group" : "Dinâmica"},
            {"value": 'Vento e temperatura 850hPa', "label": 'Vento e temperatura em 850hPa', "group" : "Dinâmica"},
            {"value": 'Vorticidade e Geopotencial 500hPa', "label": 'Vorticidade e Geopotencial em 500hPa', "group" : "Dinâmica"},
            {"value": 'Vento em 850hPa', "label": 'Vento em 850hPa', "group" : "Dinâmica"},
        ]

options_tok10 = [
            {"value": 'Acumulado Semanal', "label": 'Acumulado Semanal', "group" : "Precipitação"},
            {"value": 'Prec 24 horas', "label": 'Prec 24 horas', "group" : "Precipitação"},
            {"value": 'Acumulado total de precipitação', "label": 'Acumulado total de precipitação', "group" : "Precipitação"},
            {"value": 'Jato 200hPa', "label": 'Jato e divergência em 200hPa', "group" : "Dinâmica"},
            {"value": 'Vento e temperatura 850hPa', "label": 'Vento e temperatura em 850hPa', "group" : "Dinâmica"},
            {"value": 'Vorticidade e Geopotencial 500hPa', "label": 'Vorticidade e Geopotencial em 500hPa', "group" : "Dinâmica"},
            {"value": 'Vento em 850hPa', "label": 'Vento em 850hPa', "group" : "Dinâmica"},
        ]

options_eta = [
            {"value": 'Acumulado Semanal', "label": 'Acumulado Semanal', "group" : "Precipitação"},
        ] 

opcoes_gerais = [
            {"value": 'Acumulado Semanal', "label": 'Acumulado Semanal', "group" : "Precipitação"},
            {"value": 'Prec 24 horas', "label": 'Prec 24 horas', "group" : "Precipitação"},
            {"value": 'Acumulado total de precipitação', "label": 'Acumulado total de precipitação', "group" : "Precipitação"},
            {"value": 'Prec 24 horas e PNMM', "label": 'Prec 24 horas e PNMM', "group" : "Precipitação"},
            {"value": 'Jato 200hPa', "label": 'Jato e divergência em 200hPa', "group" : "Dinâmica"},
            {"value": 'Vento e temperatura 850hPa', "label": 'Vento e temperatura em 850hPa', "group" : "Dinâmica"},
            {"value": 'Vorticidade e Geopotencial 500hPa', "label": 'Vorticidade e Geopotencial em 500hPa', "group" : "Dinâmica"},
            {"value": 'Vento em 850hPa', "label": 'Vento em 850hPa', "group" : "Dinâmica"},
            {"value": 'Todos os campos', "label": 'Todos os campos', "group" : "Painel"},
        ]

options_merge = [
            {"value": 'Prec observada 24 horas', "label": 'Prec 24 horas', "group" : "Precipitação"},
        ] 

options_regiao = [
    {"value": 'regiao norte', "label": 'Cidades Norte'},
    {"value": 'regiao centro-oeste', "label": 'Cidades Centro-Oeste'},
    {"value": 'regiao nordeste', "label": 'Cidades Nordeste'},
    {"value": 'regiao sudeste', "label": 'Cidades Sudeste'},
    {"value": 'regiao sul', "label": 'Cidades Sul'},
    ]

modelos = [
    {"value": 'GFS', "label": 'NCEP-GFS', "group" : "Previsão curto prazo"},
    {"value": 'GEFS', "label": 'NCEP-GEFS', "group" : "Previsão curto prazo"},
    {"value": 'ECMWF', "label": 'ECMWF', "group" : "Previsão curto prazo"},
    {"value": 'ECMWF-ENS', "label": 'ECMWF-ENS', "group" : "Previsão curto prazo"},
    {"value": 'ETA', "label": 'ETA-ONS', "group" : "Previsão curto prazo"},
    {"value": 'TOK10', "label": 'TOK10', "group" : "Previsão curto prazo"},
    {"value": 'TOK30', "label": 'TOK30', "group" : "Previsão curto/médio prazo"},
    {"value": 'ECMWF-ENS-ESTENDIDO', "label": 'ECMWF-ENS-ESTENDIDO', "group" : "Previsão estendida"},
    {"value": 'GEFS-ESTENDIDO', "label": 'GEFS-ESTENDIDO', "group" : "Previsão estendida"},
]

style = {
    "textAlign": "center",
    'margin-top': '5px',
}

def server_layout():

    conteudo = html.Div([

        dmc.NumberInput(
            label="Escolha o numero de colunas para comparar",
            id='input-colunas',
            value=2,
            max=5,
            min=1,
            step=1,
            style={"width": 250},
        ),

        html.Div(id='lista-de-colunas', children=[]),

    ])

    conteudo = dbc.Container([conteudo], fluid=True, className='main')

    return conteudo

app.layout = server_layout

@app.callback(
Output('lista-de-colunas', 'children'),
Input('input-colunas', 'value'),
)
def make_grid(value):

    conteudo_divs = []

    for colunas in range(value):

        children1 = dmc.Select(id={"type": "lista-modelos", "index": colunas}, data=[x for x in modelos], value=modelos[colunas]['value'], style={"margin": 10}, classNames=select_classnames, icon=DashIconify(icon=icons_model))
        children2 = dmc.Select(id={"type": "lista-datas", "index": colunas}, style={"margin": 10}, classNames=select_classnames, icon=DashIconify(icon=icons_date))
        children3 = dmc.Select(id={"type": "lista-de-variaveis", "index": colunas}, style={"margin": 10}, searchable=True, classNames=select_classnames, icon=DashIconify(icon=icons_vars))
        children4 = html.Div(children=[], id={"type": "div-figuras", "index": colunas}, className='comparacaoimagem border-dark shadow-lg p-1 mb-2 bg-white rounded', style={'width': '100%'})

        conteudo_div = html.Div([children1, children2, children3, children4])
        conteudo_divs.append(conteudo_div)

    grid = dmc.SimpleGrid(

        cols=value,
        children=conteudo_divs,
        id='grid-comparacao',
    )

    return grid

@app.callback(
Output('lista-de-variaveis', 'data'),
Output('lista-de-variaveis', 'value'),
Input({"type": "lista-modelos", "index": ALL}, "value"),
)
def choice_vars(value):

    if value == 'GFS':
    
        options = options_gfs 

        options = [x for x in options if 'Todos os campos' not in x['value']]

    elif value == 'ETA':

        options = options_eta

        options = [x for x in options]

    elif value == 'ECMWF-ENS-ESTENDIDO' or value == 'GEFS-ESTENDIDO':

        options = options_ecmwf_gefs_estendido

        options = [x for x in options]

    elif value == 'TOK30':

        options = options_tok30

    elif value == 'TOK10' or value == 'TOK30':

        options = options_tok10

    elif value == 'MERGEGPM':

        options = options_merge

    else:

        options = opcoes_gerais

        options = [x for x in options if 'Todos os campos' not in x['value']]
        
    return options, options[0]['value']

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

animação3

Maybe I’m not doing it right…

Hi @jp123

Try changing your callback to:

@app.callback(
    Output({"type":'lista-de-variaveis', "index": MATCH}, 'data'),
    Output({"type":'lista-de-variaveis', "index": MATCH}, 'value'),
    Input({"type": "lista-modelos", "index": MATCH}, "value"),
)
def choice_vars(value):
    ....

Also, change the imports to:


from dash import Dash, html, Input, Output, MATCH

# delete the following line to stop the warning message in the console:
# import dash_html_components as html  

1 Like

That’s works !! Thanks

2 Likes