1

On a form I have an <input type = "text"> field for a 10 digit-only telephone number. I need the field as and when the user inputs (by typing or pasting) to allow 10 numbers only. When inserting a letter, symbol or space, these invalid characters should be ignored/stripped (on q01234 56789p, only 0123456789 should remain).

If the telephone number starts with 27 it must convert 27 to a 0 but keep the last digit. Pasting data starting with 27 it must keep everything after the 27 as telephone numbers beginning with 27 have 11 digits, exceeding the 10 digit limit (27123456789 must become 0123456789, not 012345678).

How can this be done as the user pastes into the field instead of waiting to loose focus first? All conditions must validate and correct input as the user attempts to go on to the next input field. This form is for typing or pasting data from logs that have either omitted the leading zero or include the +27 international code, in Firefox 66x Quantum. I don’t mind changing the input field as long as it remains a text box and not a text field or number input type.

<form>
<label>Phone Number</label><br>
<input id="PhoneNumber" type="text" minlength="10" maxlength="10" pattern="[0][0-9]" required>
</form>
3
  • 1
    developer.mozilla.org/en-US/docs/Web/HTML/Element/input/tel Commented Apr 27, 2019 at 15:46
  • As a standard, only mark the input field as incorrect, once the user has finished. - If I were you, I'd just go for the standard tel type on an input field, as Crypopat suggested. You can still specify your own regex pattern and error state Commented Apr 27, 2019 at 15:54
  • The other way around (convert 0 to +27) avoids variable length to start with. Commented Aug 16 at 2:05

3 Answers 3

3

There is actually an input type of tel, which will save you a lot of hassle. Using <input type="tel" ... would be the correct approach, and it also allows you to specify a regex to validate the phone number to your specification, using the pattern attribute.

For example:

<input type="tel" >

It is worth noting, that you will still need server-side validation, of course. You should use the same regex on both client, and server.

This is widely supported now, but if you are worried, see this answer.

Sign up to request clarification or add additional context in comments.

Comments

0

First, I would advise against removing characters immediately, as it can be counter-intuitive for the user: you don't want them to think their keyboard is broke.

Secondly, some of your requirements are contradictory. Two examples:

the input must still append a zero to the beginning of that phone number to make it 10 digits in total

[...]

All of the above conditions must validate and correct user data immediately, as and when the user inputs the data

This would mean that if the user starts typing in the empty input field, and types a "1", the rule should kick in immediately and make that phone number 10 digits in total.

Another contradiction:

Allow the input of numbers only. [...] invalid characters will be ignored/stripped

[...]

Strip international dialing codes from phone numbers, [...] +27123456789 should become 0123456789

But if the user can only type digits, then they would never be able to enter +27: already when they type the "+", it would be stripped.

This can of course not be the intended behaviour. So at least some rules should only be applied when the user somehow indicates they have finished entering the phone number. This can be done when they move the selection to a next input field.

Here is an implementation where characters other than digits and "+" are ignored/stripped immediately, and a "+" can only be entered as the left-most character.

The removal of the international dial code, and the padding with zero, will only be applied when the focus changes:

const el = document.querySelector("#PhoneNumber");

const littleClean = input => input.replace(/(\d)\D+|^[^\d+]/g, "$1")
                                  .slice(0, 12);
const bigClean = input => !input ? ""
                                 : input.replace(/^\+(27)?/, "")
                                        .padStart(10, "0")
                                        .slice(0, 10);
const format = clean => {
    const [i, j] = [el.selectionStart, el.selectionEnd].map(i => 
        clean(el.value.slice(0, i)).length
    );
    el.value = clean(el.value);
    el.setSelectionRange(i, j);
};
el.addEventListener("input", () => format(littleClean));
el.addEventListener("focus", () => format(bigClean));
el.addEventListener("blur", () => format(bigClean));
<form>
    <label>Phone Number<br>
    <input id="PhoneNumber" type="tel" minlength="10" required></label><br>
    <label>Name<br>
    <input id="Name" type="text" required></label><br>
</form>

2 Comments

thank you very much for your suggestion - this is what I need. Is it possible to have the field in your example only accept 10 digits in total? Or will just adding maxlength=10 to the html solve this?
I just added slice calls to allow up to 12 characters while the user is typing (to allow for "+27"), and 10 once the user leaves the input field.
-2
<input type="text" inputmode="numeric" pattern="[0-9]*" maxlength="11" name="phone" placeholder="phone number" required />

1 Comment

This restricts input, but how would it "... auto-format telephone numbers ..." (which the question asks for)?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.