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.
The callbacks inside “gera_comparacao” function changes the last row of each column, as follows:
So the expected is that this callback inside “gera_comparacao” funtion also trigger when the number of columns changes.
Why this happens?