Skip to content

attach ​

Puts a mask on an <input>: formats on typing and paste, keeps the caret in place, Backspace goes through literals. More in Input field.

Signature ​

ts
function attach(input: HTMLInputElement, mask: MaskInput, options?: AttachOptions): AttachedMask

interface AttachOptions {
  onChange?: (state: MaskState) => void;
  raw?: boolean;
  placeholder?: string;
}

interface MaskState { value: string; raw: string; complete: boolean; valid: boolean }

interface AttachedMask {
  readonly raw: string;
  readonly complete: boolean;
  readonly valid: boolean;
  update(mask: MaskInput, options?: AttachOptions): void;
  refresh(): void;
  destroy(): void;
}
Description
onChangeCalled on change: { value, raw, complete, valid }. A re-render without changes doesn't call it
raw (option)Input handlers (@input, v-model) get the unmasked value while the field shows the mask
placeholderA character for empty positions: '_' → +7 (___) ___-__-__, '0' → +7 (000) 000-00-00, '•', 'X' — any character, digits included. The template is visible on focus and while the field isn't complete
raw, complete, validThe current unmasked value, whether it is filled and correct (isValid)
update(mask, options?)Change the mask or options (e.g. when another country is selected)
refresh()Reformat a value written into the field from code — the caret stays in place
destroy()Remove the mask

Example ​

ts
const input = document.querySelector<HTMLInputElement>('#phone')!;
const select = document.querySelector<HTMLSelectElement>('#country')!;

const field = attach(input, phone('ru'), {
  onChange: ({ complete }) => input.classList.toggle('done', complete),
});

select.addEventListener('change', () => field.update(phone(select.value as PhoneCountry)));

See also ​