How to Clear All Input Fields Including dmc.DatePicker and dmc.NumberInput in Dash?

Hello,

I am developing a Dash application where I need to clear several types of input fields (NumberInput, TextInput, and DatePicker) with a single button click. However, only the TextInput is being cleared, while the NumberInput and DatePicker remain unchanged. Could you please advise on how to ensure the button resets all input fields correctly?

Here’s the code snippet I’m working with:

layout = html.Div([
    dmc.NumberInput(
        id='number-input',
        label='Number Input',
    ),
    dmc.TextInput(
        id='text-input',
        label='Text Input',
    ),
    dmc.DatePicker(
        id='date-input',
        label='Date Input',
    ),
    html.Button('Clear Input', id='clear-button', n_clicks=0),
    html.Div(id='output')
])

@callback(
    Output('number-input', 'value'),
    Output('text-input', 'value'),
    Output('date-input', 'value'),
    Input('clear-button', 'n_clicks')
)
def clear_input(n_clicks):
    if n_clicks > 0:
        return "", "", ""
    return dash.no_update, dash.no_update, dash.no_update

Hi @mito.kc

The default value of dmc.DatePicker() is None, so you should return None instead of an empty string.

For the NumberInput(), it seems that there’s a bug with the implementation because the default value is indeed an empty string but for some reason it doesn’t seem to work here. Maybe @snehilvj could help you more with this.

1 Like

Hi @mo.elauzei

Thank you for your advice on dmc.DatePicker() ! I tried your suggestion to return None, and it worked as expected.

1 Like

I’m still having this issue where I reset the dmc.NumberInput to ‘’ and the value remains in the input. I’ve tried numerous workarounds but has this been fixed?

Hi @jshrw1 welcome to the Dash community :slightly_smiling_face:

I just tried the code from the original post with 0.14.6 and it worked perfectly. What version are you using?

Ahh yeah you’re right. just run my code in an updated environment and it works. I was using dash 2.9.3 an dmc 0.11.1. When i upgraded to 2.18.1 and 0.14.6 respectively it worked. Thanks for your reply! @AnnMarieW

1 Like

@AnnMarieW so here is my code. Im using

dash-mantine-components==0.14.6
dash==2.18.1

for some reason when I reset the value to None, the placeholder isnt restored its just stick at 1

Hi @jshrw1

It seems like the NumberInput is not handling the None values correctly. Try using "" as a workaround.
I’ll open an issue for this on the dmc GitHub.

It seems to be because I’m using a function to return the number inputs as they’re dynamic based on the inputs. In case I want to add more inputs in the future. I have added a work around to fix the issue. I think its because the inputs are dynamically generated that when they are reset the placeholder isnt in any sort of memory so it doesnt replace it. It may be also the problem you have describe I’ll have a play in the AM and get back to this thread. I tried posting some code but had some formatting issues so I’ll try figure that out to add more context!

Hi @jshrw1

Code would be helpful. To format the code, enclose it in three back ticks. Another option is to post it to PyCafe https://py.cafe/

Actually it looks like the upstream Mantine library does not handle a None value in NumberInput. Here is the info from the Mantine docs

Value type

value, defaultValue and onChange props can be either string or number. In all cases when NumberInput value can be represented as a number, onChange function is called with a number (for example 55, 1.28, -100, etc.). But there are several cases when it is not possible to represent value as a number:

  • Empty state is represented as an empty string – ''
  • Numbers that are larger than Number.MAX_SAFE_INTEGER or smaller than Number.MIN_SAFE_INTEGER are represented as strings – '90071992547409910'
  • Numbers that consist of only multiple zeros are represented as strings – 0., 0.0, -0.00, etc.

@AnnMarieW Thats super helpful, replacing the None value with “” has worked and the dynamic features work as expected.

from dash import (
    Dash,
    html,
    dcc,
    Input,
    Output,
    State,
    callback_context,
    ALL,
    MATCH,
    no_update,
)

import dash_mantine_components as dmc
from dash.exceptions import PreventUpdate

dash._dash_renderer._set_react_version("18.2.0")
app = Dash(__name__)

# Sample IDs
_ids = ["id1", "id2", "id3"]  # Example ids


def create_input_fields(id, values=""):
    return html.Div(
        [
            dmc.NumberInput(
                id={"type": "input", "id": id, "year": year},
                placeholder=f"{id} Year {year}",
                value=values[year - 1] if values else "",
                min=0,
                style={"width": "150px", "margin": "5px"},
            )
            for year in range(1, 6)
        ],
        style={"margin-bottom": "10px"},
        id={"type": "input-container", "id": id},
    )


app.layout = html.Div(
    [
        dmc.MantineProvider(
            children=[
                # Input fields container
                html.Div(
                    [create_input_fields(id) for id in _ids], id="inputs-container"
                ),
                # Store for all data
                dcc.Store(id="all-data-store"),
                # Button container for reset buttons
                html.Div(id="button-container"),
                # Debug output for tracking changes
                html.Div(id="debug-output"),
            ]
        )
    ]
)


# Callback to update store and create reset buttons
@app.callback(
    Output("all-data-store", "data"),
    Output("button-container", "children"),
    Input({"type": "input", "id": ALL, "year": ALL}, "value"),
)
def update_store_and_buttons(values):
    ctx = callback_context
    stores = {id: ["", "", "", "", ""] for id in _ids}
    if ctx.inputs:
        for i, value in enumerate(ctx.inputs_list[0]):
            id = value["id"]["id"]
            year = value["id"]["year"]
            input_value = values[i]
            stores[id][year - 1] = input_value
    buttons = [
        dmc.Button(f"Reset {id}", id={"type": "reset", "id": id})
        for id, values in stores.items()
        if any(v != "" for v in values)
    ]
    return stores, buttons


@app.callback(
    Output({"type": "input", "id": MATCH, "year": ALL}, "value"),
    Input({"type": "reset", "id": MATCH}, "n_clicks"),
    State({"type": "input", "id": MATCH, "year": ALL}, "id"),
    prevent_initial_call=True,
)
def reset_inputs(n_clicks, input_ids):
    if not n_clicks:
        raise PreventUpdate
    # Return None for all input fields to clear them
    return [""] * len(input_ids)


# Debug callback to output current state
@app.callback(
    Output("debug-output", "children"),
    Input("all-data-store", "data"),
)
def debug_output(data):
    return f"{data}"


if __name__ == "__main__":
    app.run_server(debug=True)