Is it possible for a modal to be reset once it is closed out?

Hello all,

I am new to Plotly Dash and am trying to get my modal (using dash_bootstrap_components) to reset the inputs when the modal is clicked off of or closed. Is that possible? I have not seen anything in the documentation about it. Attached is a snippet of my code.

# Importing the necessary libraries and dependencies
from dash import Dash, Input, Output, State, html, dcc, dash_table, callback
import dash_mantine_components as dmc
import dash_bootstrap_components as dbc
import dash_daq as daq
import redis as rd
import os
import pandas as pd

# Initializing the Dash instance and chosing a color theme for layout
app = Dash(__name__, external_stylesheets=[dbc.themes.SOLAR])

# Creating the fields that will capture Customer's input
user_input = html.Div([
    dbc.Label(
        'Name:', # Change the title of the text box
        html_for='example-name-row', # ???
        width='auto'), # Shift name label in the container
    dbc.Col(dbc.Input(
        type='text', # Specify the type of input
        id='example-name-row', # Unique given id created by the user
        placeholder='Enter First and Last Name', # Change the text in the input text box
        minLength= 1, # Min length of the character that can fit in the text box
        maxLength = 80), # Max length of the character that can fit in the text box
        width='auto' #Adjust the length of the label text box
        )]
)

email_input = html.Div([
    dbc.Label(
        'Email:', # Change the title of the text box
        html_for='example-email-row', # ???
        width='auto'), # Adjusts the width of the label text
    dbc.Col(dbc.Input(
        type='email', # Specify the type of input
        id='example-email-row', # Unique given id created by the user
        placeholder='Enter Email Address'), # Change the text in the input text box
        width='auto', # Adjusts the width of the input text box
    )
])

message = html.Div([
    dbc.Label(
        'Message:', 
        html_for='example-message-row', 
        width='auto'),
    dbc.Col(dbc.Textarea(
        id = 'example-message-row',
        placeholder='Enter message',
        required = True), 
        width='auto')
])

dropdown = html.Div([ 
    dbc.Label('Reason:', html_for='dropdown', width='auto'),
    dbc.Col(dcc.Dropdown(['Bug', 'Feedback', 'Feature/Metric Request', 'Other'], '', id='dropdown'))
])

submit = html.Div(
    id = 'div-button', 
    children = [
        dbc.Col(
            dbc.Button(
                'Submit',
                color = 'dark',
                id='button-submit',
                className='me-2',
                n_clicks=0)
        )
])

# Creating a function that will encompass all of the above fields into a container and a form
def contact_form():
    form = html.Div([
        dmc.Affix(
            dbc.Button(
                'Feedback',
                color='info',
                id='open', 
                size='small'
                ), 
                position={
                    'top': 400, 
                    'left': 1855
                }, 
                style={
                    'transform': 'rotate(-90deg)',
                    'position':'absolute'
                } 
        ),
        dbc.Modal([
                dbc.ModalHeader('Feedback'),
                dbc.ModalBody('Send a message if you have a comment, question, or concern. Thank you!'),
        
        dbc.Container([
            html.Br(),
            dbc.Card(
                dbc.CardBody([dbc.Form([user_input, email_input, dropdown, message, html.Br(), submit]),
                html.Br(),        
                ]),#end cardbody
            ),#end card        
            html.Br(),
            html.Br()
        ])
        ], id='modal',
        centered=True,
        autoFocus=True,
        fade=True) # end of modal
        ])
    
    return form

# Creating the layout for the app
app.layout = html.Div([contact_form()])


# Writing the callback decorator and function to take the submitted input and write it to a dataframe
@app.callback(
    Output('modal', 'is_open'),
    Input('open', 'n_clicks'),
    State('modal', 'is_open')
)
def toggle_modal(n1,is_open):
    if n1:
        return not is_open
    return is_open

@app.callback(
    Output('div-button', 'children'),
    Input('button-submit', 'n_clicks'),
    Input('example-name-row', 'value'),
    Input('example-email-row', 'value'),
    Input('dropdown', 'value'),
    Input('example-message-row', 'value')
    )

def submit(n, name, email, dropdown, message):

    if n > 0:
        redis_instance = rd.StrictRedis.from_url(os.environ.get('REDIS_URL', 'redis://user-feedback-data-redis:a85fb14621e14ce6dbacc5e41ac7aa4c4e248a83e3b16451b54a3b43f539180f@dokku-redis-user-feedback-data-redis:6379'))
        data = pd.DataFrame({'Name':[name], 'Email':[email], 'Feedback Reason':[dropdown], 'Message':[message]})
        df = redis_instance.hset('data','data', data.to_json())
        return "Thank you for your response!!"
    else:
        return html.Div([
            dbc.Col(
                dbc.Button(
                    'Submit', 
                    color = 'info', 
                    id='button-submit', 
                    n_clicks=0
                    )
            )
        ])

yes, you could just have the inputs as additional output() in your callback and return an empty string, dictionary or whatever if the close button has been clicked

@AIMPED Thank you for you reply. Would it be possible to provide a code snippet, so that I could better understand with a visual?

I’m not sure, where the inputs are defined, in the modal itself as dcc.Input() or elsewhere. Here is an example (adapted from here) on how to do different things if clicking OK or CANCEL within the modal.

import dash_bootstrap_components as dbc
from dash import Input, Output, State, html, dcc, ctx
import dash
import plotly.express as px
import numpy as np

# design of the modal
modal = html.Div(
    [
        dbc.Modal(
            [
                dbc.ModalHeader(dbc.ModalTitle("Header"), close_button=False),
                # ^^ don't show an "X" to close the modal
                dbc.ModalBody("By click on cancel, the figure is going to be reset"),
                dbc.ModalFooter(
                    children=[
                        dbc.ButtonGroup(
                            [
                                dbc.Button(
                                    "OK",
                                    id="ok",
                                    className="m-1",
                                    n_clicks=0
                                ),
                                dbc.Button(
                                    "Cancel",
                                    id="cancel",
                                    className="m-1",
                                    n_clicks=0
                                )
                            ]
                        )
                    ]
                ),
            ],
            id="modal",
            is_open=False,
            centered=True,
            keyboard=False,
            backdrop="static",
            # ^^ don't accept keyboard interaction to close the modal (ESC)
        ),
    ]
)

app = dash.Dash(
    __name__,
    external_stylesheets=[dbc.themes.CYBORG],
    meta_tags=[
        {'name': 'viewport',
         'content': 'width=device-width, initial-scale=1.0'
         }
    ]
)
app.layout = html.Div(
    [
        dbc.Button(
            "open modal",
            id="open",
            n_clicks=0
        ),
        dcc.Graph(
            id='graph',
            figure=px.imshow(np.random.randint(0, 255, size=(10, 10)))
        ),
        modal
    ]
)


@app.callback(
    Output("modal", "is_open"),
    Output("graph", "figure"),
    Input("open", "n_clicks"),
    Input("ok", "n_clicks"),
    Input("cancel", "n_clicks"),
    State("graph", "figure"),
    State("modal", "is_open"),
    prevent_initial_call=True
)
def toggle_modal(open_modal, ok, cancel, current_figure, is_open):
    # which button triggered the callback?
    trigger = ctx.triggered_id

    # open modal has been clicked --> just open the modal and return current figure
    if trigger == 'open':
        return not is_open, current_figure

    # ok button has been clicked --> create new figure
    if trigger == 'ok':
        new_figure = px.imshow(np.random.randint(0, 255, size=(10, 50)))
        return not is_open, new_figure

    # cancel button has been clicked --> reset the figure
    if trigger == 'cancel':
        return not is_open, {}


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