OTP input
One-time passwords, PIN codes and verification codes, in a single accessible input drawn as separate slots.
Bootstrap’s otp input docs describe the markup and CSS.
How it works
Put one bsOtpInput in a bsOtp. Screen readers, password managers and SMS autofill see one ordinary text input, with autocomplete="one-time-code", drawn as a slot per character. Its maxlength sets the number of slots. Typing overwrites the slot at the caret, clicking a slot moves to it, and pasting 123-456 drops the dash. Bind the input like any text input.
Value: empty
<div bsOtp (complete)="completed.set($event)">
<input bsOtpInput maxlength="6" aria-label="Verification code" [formControl]="code" />
</div>
<p class="mt-3 mb-0 fg-3">
Value: {{ code.value || 'empty' }}
@if (completed()) {
· completed with {{ completed() }}
}
</p>Connected inputs
Set connected to merge the slots into one field with shared borders.
<div bsOtp connected>
<input bsOtpInput maxlength="6" aria-label="Verification code" />
</div>Four-digit PIN
Use a smaller maxlength for shorter codes.
<div bsOtp connected>
<input bsOtpInput maxlength="4" aria-label="PIN" />
</div>With separator
Set groups to split the slots, for codes like 123-456. The separator is decorative and never part of the value; change it with separator.
<div bsOtp [groups]="[3, 3]">
<input bsOtpInput maxlength="6" aria-label="Verification code" />
</div>Sizes
Set size to sm or lg.
<div class="vstack gap-3">
<div bsOtp size="sm">
<input bsOtpInput maxlength="6" aria-label="Small verification code" />
</div>
<div bsOtp size="lg">
<input bsOtpInput maxlength="6" aria-label="Large verification code" />
</div>
</div>Alphanumeric and masking
Only digits are accepted by default. Set type to alphanumeric or alpha to accept letters, which also changes the input’s inputmode and pattern. Set mask to show dots while keeping a text input, so the numeric keyboard and autofill still work.
<div class="vstack gap-3">
<div bsOtp connected type="alphanumeric">
<input bsOtpInput maxlength="6" aria-label="Alphanumeric code" />
</div>
<div bsOtp connected mask>
<input bsOtpInput maxlength="6" aria-label="Masked code" />
</div>
</div>Disabled
Disable the input, or its form control.
<div bsOtp connected>
<input bsOtpInput maxlength="6" aria-label="Verification code" [formControl]="code" />
</div>Validation
The slots follow the input’s validation state: from its form control, or set validation on the input.
<div class="vstack gap-3">
<div bsOtp connected>
<input
bsOtpInput
maxlength="6"
value="123456"
validation="valid"
aria-label="Valid verification code" />
</div>
<div bsOtp connected>
<input
bsOtpInput
maxlength="6"
value="123"
validation="invalid"
aria-label="Invalid verification code" />
</div>
</div>With form field
In a bsFormField, the label and help text are linked to the input, and feedback shows when the code is invalid.
<div bsFormField>
<label bsFormLabel>Verification code</label>
<div bsOtp>
<input bsOtpInput maxlength="6" [formControl]="code" />
</div>
<small bsFormText>Enter the 6-digit code sent to your phone.</small>
<div bsInvalidFeedback>Enter all 6 digits.</div>
</div>API
BsOtp
Selector: div[bsOtp] · Exported as: bsOtp
Inputs
| Name | Type | Default | Description |
|---|---|---|---|
type | 'numeric' | 'alphanumeric' | 'alpha' | 'numeric' | Characters the input accepts. |
mask | boolean | false | Shows a dot instead of each character. |
groups | number[] | null | null | Group sizes, with a separator between groups. |
separator | string | '·' | Character shown between groups. |
connected | boolean | false | Merges the slots into one field. |
size | 'sm' | 'lg' | null | null | Size of the slots. |
Outputs
| Name | Type | Description |
|---|---|---|
complete | string | Emits the code when every slot is filled. |
BsOtpInput
Selector: input[bsOtpInput] · Exported as: bsOtpInput
Inputs
| Name | Type | Default | Description |
|---|---|---|---|
maxlength | number | 6 | Number of characters and slots. |
autocomplete | string | 'one-time-code' | The input’s autocomplete. |
id | string | generated | Element id. Generated when not set, and used for the field’s label. |
validation | 'auto' | 'valid' | 'invalid' | 'none' | 'auto' | Validation styles. auto follows the bound Angular form control. |
Methods
| Name | Type | Description |
|---|---|---|
focus() | void | Focuses the input on the first empty slot. |
clear() | void | Clears the value and focuses the input. |