개발/Dash

[Dash]Python Dash Callback (3) 팝업창에 경고 메시지 띄우기 + 콜백 합치기

moonzoo 2024. 1. 17. 16:16

 

Action 1. 팝업창에서 원하는 명령을 수행하지 않을 시 경고 메시지 띄우기

dbc.toast , dbc.Alert 등은 사용자에게 메시지를 표시하는 데 사용하는 컴포넌트 입니다.

  • dbc.Alert를 사용해 dbc.Modal의 ModalBody에서 질문과 답변을 입력하지 않을 시 경고 메시지를 띄웁니다.
  • Modal의 팝업창을 닫고 다시 여는 버튼인 '수정하기' 를 클릭할 시 기존에 있던 경고 메시지를 제거합니다.

Callback_context

callback_context는 Dash에서 제공하는 객체로, 현재 콜백이 실행된 맥락에 대한 정보를 포함하고 있습니다. 이 객체를 사용하여 어떤 입력(Input)이 콜백을 트리거했는지, 혹은 어떤 상태(State)가 현재 콜백에 영향을 미쳤는지 등을 알 수 있습니다.

 

아래와 같은 에러가 발생했을 때 사용하실 수 있습니다.


Output 11 (modal-data-store.data) is already in use. To resolve this, set `allow_duplicate=True` on duplicate outputs, or combine the outputs into one callback function, distinguishing the trigger by using `dash.callback_context` if necessary

 

Dash에서는 기본적으로 한 출력(Output)을 여러 콜백에서 사용할 수 없습니다. 따라서, 동일한 출력을 공유하는 콜백을 통합하거나, 중복 출력을 허용하는 방법(allow_duplicate=True) 중 하나를 선택해야 합니다. 일반적으로는 콜백을 통합하는 것이 더 깔끔하고 관리하기 쉬운 접근 방법입니다.

통합 콜백에서는 dash.callback_context를 사용하여 어떤 입력(Input)이 트리거된 것인지 확인하고, 그에 따라 적절한 로직을 실행합니다.

 

아래 예시에서는 model_edit_question, model_edit_answer 출력을 사용하는 모든 콜백을 하나의 콜백으로 통합했습니다.

dbc.Modal([dbc.ModalHeader("표준셋 추가하기"),
                        dbc.ModalBody([
                            html.Div([
				dbc.Alert(
                                    "질문과 답변을 모두 입력해주세요.",
                                    id="edit_warning_alert",
                                    color="danger",
                                    is_open=False,  # 기본적으로 숨겨져 있음
                                    dismissable=True)                                              
                        ])
                        ]),
                        dbc.ModalFooter([
                            dbc.Button("수정하기", id="edit_standard_set",
                                       className="mr-2"),
                            dbc.Button("닫기", id="edit_close",
                                       className="ml-auto")])
                        ], id="modal_edit", size="lg", is_open=False)
from dash import callback_context


@app.callback(
    [Output('modal_edit_question', 'invalid'),
     Output('modal_edit_answer', 'invalid'),
     Output('edit_warning_alert', 'is_open')],
    [Input('edit_standard_set', 'n_clicks'),
     Input('modal_edit_open', 'n_clicks')],
    [State('modal_edit_question', 'value'),
     State('modal_edit_answer', 'value')]
)
def update_modal_edit(n_edit, n_open, question, answer):
    triggered_id = callback_context.triggered[0]['prop_id'].split('.')[0]

    if triggered_id == 'edit_standard_set':
        question_invalid = not (question and question.strip())
        answer_invalid = not (answer and answer.strip())
        show_warning = question_invalid or answer_invalid
        return question_invalid, answer_invalid, show_warning

    elif triggered_id == 'modal_edit_open':
        # '수정하기' 버튼을 클릭하면 경고 메시지를 숨깁니다.
        return False, False, False

    return dash.no_update

 

코드 설명

  • @app.callback :  데코레이터는 Dash 애플리케이션의 인터랙티브한 동작을 정의하는 데 사용됩니다.
  • 이 콜백 함수는 modal_edit_questionmodal_edit_answer 필드의 유효성을 검사하고, 필요한 경우 경고 메시지를 표시합니다. 질문과 답변이 공백일 경우 유효성 검사를 하고 경고 메시지를 띄웁니다.
  • Input은 이 함수가 반응할 이벤트를 정의합니다. 여기서는 'edit_standard_set''modal_edit_open' 버튼의 클릭 이벤트에 반응합니다.
  • State는 콜백 함수가 사용할, 하지만 이벤트 트리거로 사용하지 않는 데이터를 정의합니다. 여기서는 'modal_edit_question'과 'modal_edit_answer' 필드의 값을 사용합니다.
  • triggered_id는 어떤 입력 요소가 콜백 함수를 트리거한 것인지를 확인합니다. callback_context.triggered[0]['prop_id'].split('.')[0]는 트리거한 요소의 ID를 가져옵니다.
  • if triggered_id == 'edit_standard_set' 부분에서는 '팝업창 안의 수정하기' 버튼이 클릭되었을 때 질문과 답변 필드의 내용이 적절히 채워져 있는지 검사합니다. 만약 하나라도 비어 있거나 공백 문자만 포함되어 있다면, 해당 필드를 유효하지 않음(invalid)으로 표시하고, 경고 메시지(show_warning = dbc.Alert)를 활성화합니다.
  • elif triggered_id == 'modal_edit_open''팝업창 바깥의 수정하기' 버튼을 클릭했을 때 경고 메시지를 숨기는 로직입니다. 즉, 사용자가 '수정하기' 버튼을 다시 클릭하면, 이전에 표시된 경고 메시지가 숨겨집니다.
  • return dash.no_update는 콜백이 트리거된 요소가 'edit_standard_set' 또는 'modal_edit_open' 버튼이 아닌 경우, 아무런 동작도 하지 않고 현재 상태를 유지하도록 합니다.