Black Lives Matter. Please consider donating to Black Girls Code today.

How to use the pattern attribute of an Input?

Hello

I try to use a regex pattern to check the contains of an Input field. I want to check if the string is a True Hex color (to save space I would like to avoid the color picker from DAQ). To do so, I filled the pattern attribute of the Input such as:

#!/usr/bin/env python3
# -*- coding=utf-8 -*-

import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output

app = dash.Dash(__name__)

app.layout = html.Div(children=[
    dcc.Input(
        id="color-value",
        debounce=True,
        placeholder="#000000",
        type="text",
        pattern=u"^#([A-Fa-f0-9]{6}$"
    ),
    html.Div(html.P(id="text"))
])

@app.callback(
    Output("text", "children"),
    [Input("color-value", "value"), 
     Input("color-value", "pattern")]
)
def write_text(value, pattern):
    print(pattern)
    return value

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

But whatever I write in the input, a True or a wrong color Hex code, I got the same result and nothing change.

Thanks for your help

dash==1.7.0
dash-core-components==1.6.0
dash-html-components==1.0.2
dash-renderer==1.2.2

I don’t think you want the pattern to be an input that will trigger your callback. I believe the value of the callback will only change if the input passes the pattern condition.

Yes I don’t want the pattern as an input. There, it was just a test to check the current value of the pattern attribute.

And yes, whatever the value of the input, the callback is triggered and the text is printed in the div.

I also try with or without the debounce option but it does not change the result. If you remove the debounce option there is not check of pattern because the text is printed in the div on the fly.

You can try with this kind of app (without the pattern in the callback):

import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output
 
app = dash.Dash(__name__)
 
app.layout = html.Div(children=[
    dcc.Input(
        id="color-value",
#        debounce=True,
        placeholder="#000000",
        type="text",
        pattern=u"^#([A-Fa-f0-9]{6}$"
    ),
    html.Div(html.P(id="text"))
])
 
@app.callback(
    Output("text", "children"),
    [Input("color-value", "value")]
)
def write_text(value):
    return value
 
if __name__ == "__main__":
    app.run_server(debug=True)

If you only want to check the value of the pattern attribute, use State('color-value', 'pattern')

Looks like you have an open paren ( in your pattern regex…I’m not a regex expert but when I tested your regex via an online tool, the ( caused validation errors.

I’ll try to test your code this evening…not able to right now.

Oh … You were True. The open parenthesis is an error there…
Really sorry about that.

Now, the callback is still triggered but the field turn red until the contains is ok.

No apologies…just wanted to ensure it wasn’t a cause of your issue.

Again, won’t be able to test your code until this evening…but is the field turning red assoc. with whether or not you have debounce set?

Yes, it works with or without the debounce option. The field turn red while the string is wrong.

Here is a full working example with a regex check to avoid to use the string if it is wrong:

Thanks again

import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output
import re

app = dash.Dash(__name__)

app.layout = html.Div(children=[
    dcc.Input(
        id="color-value",
        debounce=True,
        placeholder="#000000",
        type="text",
        pattern=u"^#[A-Fa-f0-9]{6}$"
    ),
    html.Div(html.P(id="text"))
])

@app.callback(
    Output("text", "children"),
    [Input("color-value", "value")]
)
def write_text(value):

    patt = re.compile(r"^#[A-Fa-f0-9]{6}$")

    if value is not None and  patt.match(value):
        return value
    else:
        return "WRONG"

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

I ran you code and all looks ok. It appears Dash applies coloring to indicate the pattern has not yet been satisfied.

Not sure if you have discovered dash-bootstrap-components yet, but I modified your code slightly to illustrate. You may appreciate this in your design. Check it out here

import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output, State
import re
import dash_bootstrap_components as dbc


app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])

app.layout = html.Div(
    children=[
        dbc.Row(
            [
                dbc.Col(
                    [
                        dbc.Input(
                            id="color-value",
                            debounce=True,
                            placeholder="#000000",
                            type="text",
                            pattern=u"^#[A-Fa-f0-9]{6}$",
                            valid=False,
                            maxLength=7,
                            minLength=7,
                        ),
                        html.Div(html.P(id="text"))
                    ],
                    width=3,
                ),
            ],
        ),
    ]
)

@app.callback(
    [Output('color-value', 'valid'),
     Output('color-value', 'invalid')],
    [Input("color-value", "value")],
    [State('color-value', 'pattern')])
def write_text(value, pattern):
    patt = re.compile(pattern)

    if not value:
        return dash.no_update, dash.no_update

    if patt.match(value):
        return True, False
    else:
        return False, True

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