📌
plotly Dash clickのタイミングのみで2つのinputの値を読み込む
課題
送信ボタンをトリガーとして2つの入力を読み込もうとプログラムを書いたところ、inputの変化もトリガーとなってしまった
app.layout = html.Div([
html.Div(
[
dbc.Form(
[
dbc.FormGroup(
[
dbc.Label("Column Name", className="mr-2"),
dcc.Input(
id = "input-col-name",
type = "text",
placeholder="Item Name",
),
],
className="mr-3",
),
dbc.FormGroup(
[
dbc.Label("Record Count", className="mr-2"),
dcc.Input(
id = "input-row-count",
type = "text",
placeholder="Record Count",
),
],
className="mr-3",
),
dbc.Button("Submit", id='submit-val', n_clicks=0, color="primary"),
],
inline=True
)
]
),
html.Div(id="table1")
])
@app.callback(
Output('table1', 'children'),
[Input('submit-val', 'n_clicks'),
Input('input-col-name', 'value'),
Input('input-row-count', 'value')]
)
def update_output(n_clicks, col_name:str, row_count:int):
if col_name and row_count:
df.create_numeric(col_name, int(row_count))
result = df.publish()
data = result.to_dict('rows')
columns = [{"name": i, "id": i,} for i in (result.columns)]
return dt.DataTable(data=data, columns=columns)
else:
return
解決の糸口
Inputの考え方が間違っていた
Inputは、Callback関数の入力になるが、Javascriptなどにもあるwatcherの役割があるため、valueに変化があり次第それをトリガーに関数を発動させてしまう。どちらも入力されていないと発動しないようにいくらチェックを入れても、本来の動作である、ボタンでの動作の前に動作してしまう
解決方法
Stateを使う
DashのStateをCallbackの引数にすると、変化によっては発動しないものの、関数の入力にすることができる(Stateが変わったら検知するもの ではないことに注意)
Dashのドキュメントにも、そのような使い方をすると記述してある
Dash App With Stateを参照
# 訂正前
Input('input-col-name', 'value')
Input('input-row-count', 'value')
#訂正後
State('input-col-name', 'value')
State('input-row-count', 'value')
Discussion