Input OTP

An input for one-time passwords and verification codes, rendered as individual character slots

<dui-input-otp max-length="6"/>

Usage

The dui-input-otp Tag Helper renders a segmented input for one-time passwords and verification codes. It is backed by a single hidden <input> that holds the whole code — so it model-binds and posts back like any other text field — overlaid on the individual character slots. A small del-input-otp web component distributes what you type into the slots, moves the active slot and caret, and enforces the allowed character pattern.

Use the max-length attribute to control how many characters the code has.

<dui-input-otp max-length="6"/>

Input OTP only submits a value when you set asp-for or name. Just like a native input without a name, an Input OTP without one (such as most of the examples on this page) renders and is fully interactive but posts nothing. Use asp-for to model bind, or set name to post a value without binding.

Examples

Number of digits

Use the max-length attribute to set the number of slots. It defaults to 6.

<dui-input-otp max-length="4"/>

Groups

Use the groups attribute to split the slots into groups, separated by a separator. Provide a comma-separated list of group sizes — the sizes must add up to max-length (when both are set), otherwise the total is taken from the groups.

<dui-input-otp groups="3,3"/>

Separator

A separator is rendered automatically between groups. Supply more than two groups to add multiple separators.

<dui-input-otp groups="2,2,2"/>

Pattern

Use the pattern attribute to constrain the allowed characters with a regular expression — any input that would make the value fail to match is rejected. It defaults to digits only (^\d*$). Pair it with inputmode to control the on-screen keyboard.

<dui-input-otp max-length="6" pattern="^[a-zA-Z0-9]*$" inputmode="text"/>

Composition

For full control over the layout, compose the slots by hand with the dui-input-otp-group, dui-input-otp-slot, and dui-input-otp-separator Tag Helpers instead of letting groups generate them. Slots take their position automatically in document order.

<dui-input-otp max-length="6">
    <dui-input-otp-group>
        <dui-input-otp-slot/>
        <dui-input-otp-slot/>
        <dui-input-otp-slot/>
    </dui-input-otp-group>
    <dui-input-otp-separator/>
    <dui-input-otp-group>
        <dui-input-otp-slot/>
        <dui-input-otp-slot/>
        <dui-input-otp-slot/>
    </dui-input-otp-group>
</dui-input-otp>

Model binding

The dui-input-otp Tag Helper has full support for ASP.NET Core model binding using the asp-for attribute. Bind it to a string and the whole code posts straight back to the property.

When using model binding, DuneUI will automatically wrap the input inside a Field with the correct label and description derived from data attributes. You can opt out of this behavior by setting the render-field attribute to false.

<dui-input-otp asp-for="OneTimePassword" groups="3,3"/>
public class ModelBindingModel
{
    [Display(
        Name = "One-time password",
        Description = "Enter the 6-digit code we sent to your phone."
    )]
    public string OneTimePassword { get; set; } = "123";
}

Validation

Validation works like any other model-bound field. Add validation attributes to your model and the slots reflect the invalid state, with the error message rendered below.

<dui-input-otp asp-for="OneTimePassword" groups="3,3"/>
public class ValidationModel
{
    [Display(
        Name = "One-time password",
        Description = "Enter the 6-digit code we sent to your phone."
    )]
    [Required(ErrorMessage = "Enter the complete 6-digit code")]
    [StringLength(6, MinimumLength = 6, ErrorMessage = "Enter the complete 6-digit code")]
    public string OneTimePassword { get; set; } = "123";
}

Manual Validation

If you're not using ASP.NET Core model binding, you can manually indicate validation errors by setting the aria-invalid attribute to true. This applies the destructive styling to the slots.

The error message can be displayed using either a dui-field-error Tag Helper (when using explicit fields) or the error attribute (when using implicit fields).

<dui-field>
    <dui-label>One-time password</dui-label>
    <dui-input-otp aria-invalid="true" groups="3,3"/>
    <dui-field-error>Enter the complete 6-digit code</dui-field-error>
    <dui-field-description>
        Enter the 6-digit code we sent to your phone.
    </dui-field-description>
</dui-field>
<dui-input-otp
    label="One-time password"
    description="Enter the 6-digit code we sent to your phone."
    error="Enter the complete 6-digit code"
    aria-invalid="true"
    groups="3,3"/>

Disabled

Add the disabled attribute to prevent the user from interacting with the input.

<dui-input-otp max-length="6" value="123" disabled="true"/>

On this page