What is the best way to create a React text box that exclusively accepts numeric values or remains empty, and automatically displays the number keypad on mobile devices?

While there are numerous similar questions on StackOverflow, none of them fully address all of my requirements in a single solution. Any assistance would be greatly appreciated.

The Issue at Hand

Within my React application, I am in need of a text box that possesses the following attributes:

  1. Strictly allows the input of digits - no minus signs, decimal points, letters, or any characters other than the digits 0-9.
  2. Automatically triggers the number keypad on both iOS and Android devices.
  3. Allows for further customization regarding which numbers can be entered, such as restricting it to only 4 digits.
  4. Automatically removes leading zeroes; for example, if a user types 02, it should correct to just 2.
  5. Permits an empty text box while distinguishing between an empty field and a value of 0.

Current Implementation

https://codepen.io/micahrl/pen/RwGeLmo

The existing code allows non-digit characters to be typed, resulting in a interpretation of the input as NaN. For instance, a user could enter 2f or asdf, prompting the page to display You typed: NaN.

In addition, although the text box initially loads empty, users cannot type something and then delete it back to an empty state. Trying to delete all text from the input box will insert a 0 instead.

Furthermore, the current code does not consistently trim leading zeroes, causing issues when attempting to restrict the number to four digits. Typing 01 may not remove the leading zero; entering 01111 might result in

1111</code on some browsers, which is acceptable, but on others, typing <code>01111
leads to 0111, presenting a problem.

Attempted Solutions

By setting type="number" on the input element, any non-numeric entry will produce an empty string within event.target.value in setNumWrapper. This makes it challenging to differentiate between a truly empty string (indicating all text has been deleted by the user) and invalid input (such as typing a non-numeric sequence like asdf).

Considering switching the input element to type="text" could potentially resolve this issue, were it not for the fact that specifying type="number" seems necessary to trigger the number keypad on mobile operating systems like iOS and Android.

Answer №1

Thanks to some experimentation and guidance from @Keith in a comment, I have managed to resolve the majority of my issues.

I have created a modified version of the codepen linked in my initial question, which includes the changes I implemented: https://codepen.io/micahrl/pen/GRjwqdO.

Determining Input Validity

@Keith directed me towards validity.badInput (https://developer.mozilla.org/en-US/docs/Web/API/ValidityState/badInput). This allowed me to distinguish between empty input fields and inputs containing non-numeric characters.

To address this, I included the following snippet at the start of setNumWrapper():

    if (event.target.value === "") {
      if (event.target.validity.badInput) {
        // Revert text box and number values to previous valid state
        inputRef.current.value = String(num);
        setNum(num);
      } else {
        // Clear all values if text box is emptied
        inputRef.current.value = "";
        setNum(NaN);
      }
      return;
    }

In addition, I utilized useRef() to create an inputRef, assigning it to the <input> element.

This addresses most of issue #5 as well as a portion of issue #1 (although one minor problem remains).

Removing Leading Zeros

To tackle this, I simply used the existing inputRef to update the value within the <input> element at the conclusion of setNumWrapper():

inputRef.current.value = String(newNum);

As the value of the <input> element is always a string, converting the number to a string automatically eliminates any leading zeros, if present.

Outstanding Issue: Invalid Input Accepted When Text Box is Empty

If the text box is blank, users can input non-numeric characters without triggering the execution of setNumWrapper(). Adding a console.log() statement at the beginning of

setNumWrapper()</code will not log anything for alphabetic entries, but will for numeric ones.</p>
<p>While this cannot be rectified using <code>setNumWrapper()
, it is a relatively minor concern. On mobile devices, the number keypad restricts non-numeric input, offering sufficient control. Although on desktops, users can still type letters, the app's rules clearly indicate only numbers are permitted, making this acceptable for now.

If there is a solution for this particular issue, I am open to suggestions.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Select an option from the navigation bar - the chosen item will remain highlighted

My Navbar code looks like this: <Navbar.Collapse> <Nav> <NavItem eventKey={1} href={`${process.env.PUBLIC_URL}/`}> Blah </NavItem> <NavItem eventKey={1} href={`${process.env.PUBLIC_URL}/SomePage`} ...

Connecting AWS Amplify Datastore to Material-UI datagrid

I am utilizing an AWS Amplify Datastore and I need to connect the data to an MUI datagrid. My query to the Datastore looks like this: const stocks = await DataStore.query(Stock) The resulting data is structured as follows: Stock { id: '7991c45e ...

What is the best way to center a label horizontally in Material UI within a grid layout?

I need help centering my label horizontally within a material UI grid using GRID API. Can someone please advise me on how to achieve this? https://codesandbox.io/s/007k3v472w <div className="search-container"> <Grid contain ...

Issue with custom hook causing rerender when returning an object

I created a custom hook that returns an object. export const useValue = (paramValue = undefined, options = undefined) => { const [value, setValue] = useState(''); const _setValue = (value, options = undefined) => { setValue(val ...

What's the most efficient way to iterate through this Array and display its contents in HTML?

I'm struggling to sort a simple array and I think the issue might be related to the time format. I'm not sure how to reference it or how I can properly sort the time in this array format for future sorting. //function defined to input values ...

Encountering an Object Type Unknown error while working with Typescript and React

I am currently working on building a chatbox in React using TypeScript and Firebase. Below is the code for my Room and Message components: function ChatRoom() { const messagesRef = firestore.collection('messages'); const query = messagesRef.o ...

Development versions of npm libraries

Lately, I came across a library called react-3d-components that offers some d3 react components with basic charts. It's an impressive collection of components. However, when trying to access the source code due to incomplete documentation, I found my ...

Update the HTML weather icon with data from JSON

I have a collection of weather icons stored on my computer. How can I customize the default weather icons with my own set of icons? In the JSON file, there is a variable like this: "icon":"partlycloudy" <html> <head> <script src="http://c ...

Creating a model for a different user involves several steps that can be easily

Recently, I have been working on a project involving user interactions such as following other users and viewing their content. Using technologies like Prisma, GraphQL, and Nexus, I decided to create a following model today. The model structure is as follo ...

Creating TypeScript domain objects from JSON data received from a server within an Angular app

I am facing a common challenge in Angular / Typescript / JavaScript. I have created a simple class with fields and methods: class Rectangle { width: number; height: number; area(): number { return this.width * this.height; } } Next, I have a ...

Explaining the process of defining an object type in TypeScript and the conversion from JavaScript

Currently, I am attempting to enhance the background of a React website developed in typescript (.tsx) by incorporating particles. My approach involves utilizing the particle-bg component available at: https://github.com/lindelof/particles-bg However, whe ...

Retrieve information from deeply nested JSON and showcase using Vue-Multiselect

My goal is to fetch data from the server and present it in Multiselect using nested JSON, which can be done through Vue-Multiselect. Once displayed, I should have the ability to add new tags as needed, essentially updating the data. While I can display o ...

Obtaining data from a CSV file and transforming it into JSON format results in an array

Currently, I am working on a function that takes a JSON object and prints it out as strings: GetAllArticles: (req, res) => { var allArticles = getAllArticles(); res.setHeader("Content-Type", 'application/json'); res.w ...

Issue with the react-scripts package when running the npm build command

Attempting to compile a project for the first time on a new application using npm run build resulting in the following error: client/node_modules/.bin/react-scripts: line 11: exec: node: not found So far, I have tried: chmod +x node_modules/.bin/react-sc ...

"Step-by-step guide on populating a select box with data from the scope

Hey everyone, I'm new to using Angular and hoping for some help with a simple question. I've created a form (simplified version below) that I want users to see a live preview as they fill it out. Everything was going smoothly with regular field ...

Encountering an error with the React Material-UI Datagrid after completing the app development process

I'm facing an issue now. Initially, the console was fine before building my App. However, after building it, the console is logging an error. view image here In my opinion, the cause of this error lies in the row data within the Data-grid. The consol ...

Is it necessary for the React generic type prop to be an extension of another type

I have recently started using TypeScript and I am facing a confusion regarding passing generic types into my higher-order component (HOC). My objective is to pass the component props as a generic type in order to have the Component with those specific type ...

Securing user access and storing authentication tokens in NextJS

Currently utilizing NextJS for Server-side Rendering Our authentication method involves the use of JWT In a standard React application, we can employ JWT for each server request to retrieve data However, some pages return varied data based on whether th ...

Is it possible to utilize X-Y coordinates as repositories for values beyond just X-Y coordinates themselves?

I am in the process of creating a tile-based grid and I need to expand the X-Y coordinates to include additional values for determining characteristics of each tile, such as resources (for example, food, water, stone, lumber) within a game context. Conside ...

The system does not acknowledge the command 'Working' as either internal or external

I encountered an issue after creating a React app with npx create-react-app and then trying to start the application using npm start The error displayed was as follows: npm start > <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data- ...