Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to customise `<input>` element with tighter restrictions

I have a html <input> element that I want to accept only numbers and to be recognised on mobile devices as a number field. I also want invalid characters to be swallowed, just like for standard type=number swallowing disallowed characters.

I've tried the obvious type=number but it has a number of shortcomings. Specifically it allows 'e', '+' and '-' (at least in chrome), but these were easy to fix with some JS. The real problem is with the '.' character, I want to be able to enter floating point numbers e.g. '0.10', '5.5054', but don't want to be able to enter invalid strings like '0.10.1' for instance. I tried to resolve this by allowing only 1 '.' at a time but this failed as the input.value gets massaged by the browser e.g. '5.' becomes '5', '5..' becomes null (!) and it seems impossible to get the raw string value typed in the input. The above means checking for existing '.'s and taking action appears to be a dead end...

Core questions:

  1. Is there a way I missing to inspect and conform the input?
  2. 'Is there a way of marking an input as a number without the logistical baggage of type=number?

Note:
* I realise that you can paste whatever you want in, I consider that behaviour pathological and shouldn't be covered by input prevention.

Update

To clarify, I have already tried keypress, keydown etc events and they aren't adequate as I want to see how many '.'s exist in the input currently to choose whether or not to allow another. At this point the input.value has been massaged by the browser to remove '.'s. I want to conditionally allow characters based on the current number of '.'s that have been entered.

Example

HTML (angular style binding for brevity)

<input type="number" (keydown)="keyDown()">

JS

function keyDown($event: KeyboardEvent) {
  const inputField = // obtain reference to input element
  const value = inputField.value;
  if ( value.indexOf('.') !== -1 && $event.key === '.') { // disallow another . if one is present
    // ! input field prunes . so this check isn't sufficient
    $event.preventDefault();
    return;
  }

  // This is the crux of the problem e.g.
  // type 5. into input field, value === 5
  // type 5.. into the input field, value === null
  // Since the . char is removed by the input element there's no way to know how many are present!
  console.log(value);
}

Summary

  1. Is there a way to signal that an <input> is of type number without using the type=number attribute setting.
    1. i.e. mobile devices recognise and display number pad etc
  2. For an <input> that has type=number is there a way to swallow all key input that doesn't result in a valid number
    1. Before the character is added to the input by the browser, no janky deletion on keyup
like image 726
radman Avatar asked Aug 30 '19 05:08

radman


People also ask

How do you set limits on input type numbers?

Complete HTML/CSS Course 2022 To limit an HTML input box to accept numeric input, use the <input type="number">. With this, you will get a numeric input field. After limiting the input box to number, if a user enters text and press submit button, then the following can be seen “Please enter a number.”

How do I limit input range in HTML?

The max attribute specifies the maximum value for an <input> element. Tip: Use the max attribute together with the min attribute to create a range of legal values. Note: The max and min attributes works with the following input types: number, range, date, datetime-local, month, time and week.

How do you style input elements in CSS?

Styling Input Fields If you only want to style a specific input type, you can use attribute selectors: input[type=text] - will only select text fields. input[type=password] - will only select password fields. input[type=number] - will only select number fields.


1 Answers

Is there a way to signal that an <input> is of type number without using the type=number attribute setting. i.e. mobile devices recognise and display number pad etc

Use inputmode="decimal" instead of type="number" to signal a mobile device to use a number pad keyboard input. This way you can continue to use type="text" and process the input as needed.

See MDN for more info and inputtypes.com to test on a device.

like image 188
Gone Avatar answered Oct 15 '22 06:10

Gone