What could be causing the input event not to be triggered consistently when I select or highlight text?

I have implemented a 4-digit pin field with a specific behavior: when a field is filled, the focus automatically shifts to the next field (the cursor moves to the next input field). If text in a field is deleted, the text in that field is also removed and the cursor moves back to the previous pin field.

However, there seems to be an issue where sometimes, if a field with text is highlighted and overwritten by typing another key (e.g., to correct a mistake), the input event is not triggered, causing the cursor to remain in the same field instead of moving to the next one. This inconsistency can lead to a poor user experience, and I need to find a way to ensure that the cursor always switches pin fields when highlighted text is overwritten.

Below are the relevant parts of the code:

data() {
  return {
    focusIndex: 1,
    inputOne: '',
    inputTwo: '',
    inputThree: '',
    inputFour: '',
    numberOfPinFields: 4,
  };
},

mounted() {
// this highlights the first pin field
  this.$refs[this.focusIndex].focus();
},

methods: {
  handlePinFieldDeletion() {
    if (this.focusIndex > 1) {
      this.focusIndex -= 1;
    }
  },
  
  handlePinFieldInput(value, maxNumberOfFields) {
    this.$nextTick(() => {
     // after the focus index from the input field watch below is updated, increase the focusIndex value
       if (value.length === 1 && this.focusIndex < maxNumberOfFields) {
          this.focusIndex += 1;
        }
      });
    },
  ensurePinFieldHasOneInput(value) {
    return value.slice(0, 1);
  },
  highlightOnFocus(e, focusIndex) {
    // highlight the text
    e.target.select();
    // set the new focus index
    this.focusIndex = focusIndex;
  },
 }
 
 watch: {
  focusIndex(newValue) {
    this.$refs[newValue].focus();
  },
  inputOne(newValue) {
    // set focus index of first otp input field to 1 when it changes.
    // This will help with situations where the user doesn't use the input fields in numerical order
    this.focusIndex = 1;
    this.inputOne = this.ensurePinFieldHasOneInput(newValue);
  },

  inputTwo(newValue) {
  // set focus index of first otp input field to 2 when it changes.
  // This will help with situations where the user doesn't use the input fields in numerical order
    this.focusIndex = 2;
    this.inputTwo = this.ensurePinFieldHasOneInput(newValue);
  },

  inputThree(newValue) {
  // set focus index of first otp input field to 3 when it changes.
  // This will help with situations where the user doesn't use the input fields in numerical order
    this.focusIndex = 3;
    this.inputThree = this.ensurePinFieldHasOneInput(newValue);
  },
  inputFour(newValue) {
    // set focus index of first otp input field to 4 when it changes.
    // This will help with situations where the user doesn't use the input fields in numerical order
    this.focusIndex = 4;
    this.inputFour = this.ensurePinFieldHasOneInput(newValue);
  },
  }
<form>
  ...
  <q-input
    type="password"
    input-class="text-center"
    maxlength="1"
    @keyup.delete="handlePinFieldDeletion"
    @input="handlePinFieldInput($event, numberOfPinFields)"
    v-number-only
    @focus="highlightOnFocus($event, 1)"
    borderless
    ref="1"
    v-model="inputOne"
  />
  <q-input
        type="password"
        input-class="text-center"
        maxlength="1"
        v-number-only
        @focus="highlightOnFocus($event, 2)"
        @keyup.delete="handlePinFieldDeletion"
        @input="handlePinFieldInput($event, numberOfPinFields)"
        borderless
        ref="2"
        v-model="inputTwo"
      />
      <q-input
        type="password"
        input-class="text-center"
        maxlength="1"
        v-number-only
        @focus="highlightOnFocus($event, 3)"
        @keyup.delete="handlePinFieldDeletion"
        @input="handlePinFieldInput($event, numberOfPinFields)"
        borderless
        ref="3"
        v-model="inputThree"
      />
      <q-input
        type="password"
        input-class="text-center"
        v-number-only
        @focus="highlightOnFocus($event, 4)"
        maxlength="1"
        @keyup.delete="handlePinFieldDeletion"
        @input="handlePinFieldInput($event, numberOfPinFields)"
        borderless
        ref="4"
        v-model="inputFour"
      />
  ...
</form>

Answer №1

After conducting several tests, I have identified the issue within the watch function when it comes to overwriting with the same value. For example, if field 1 was previously highlighted and updated by 5, and then updated by another 5.

Code snippet:

 watch: {
  focusIndex(newValue) {
    this.$refs[newValue].focus();
  },
  inputOne(newValue) {
    this.$q.notify({
        message: 'inputOne changed',
        caption: 'moments ago',
        color: 'secondary'
      })

Answer №2

The maxLength attribute has an interesting behavior where it does not trigger an input event when the input field reaches its maximum limit.

I found that the pin field sometimes worked and sometimes didn't after the highlighted value was overwritten. This inconsistency seemed to be due to the fact that if the user entered the same value as before (thus overwriting it with no actual change), the input event wouldn't fire. However, if a different value was used to overwrite the previous one, the event would trigger.

This discovery was made through trial and error, as I couldn't find confirmation of this behavior anywhere else. To resolve the issue, I removed the maxLength attribute and refactored the code, leading to success. The updated code can be seen below.

<script>
const generatePinInputs = (numberOfPinFields) => {
  const objectOfPinFields = {};
  // create an array of values for the number of pin fields
  Array(numberOfPinFields).fill('').forEach((field, index) => {
    objectOfPinFields[index + 1] = field;
  });
  return objectOfPinFields;
};
export default {
  name: 'app-pin',
  props: {
    numberOfPinFields: {
      type: Number,
      default: 4,
    },

  },
  mounted() {
    // switched from quasar's q-input to input because of error thrown about v-model mutating prop value
    this.$nextTick(() => {
      // After all asynchronous actions (including dialog popup showing pin fields), focus on the first input
      this.$refs[1][0].focus();
    });
  },
  data() {
    return {
      pinInputs: generatePinInputs(this.numberOfPinFields),
    };
  },


// rest of the code is unchanged...

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

What is the process for dynamically altering the source file of VueRouter?

Hello, I am working on a project that involves multiple roles using VueJs and Laravel. Laravel is used as the back-end while Vuejs serves as the front-end. The project has three different roles: User, Modirator, and Editor. Here is a snippet of my code ...

Utilizing JavaScript to retrieve input names from arrays

This is the HTML form that I am currently working with: <form action="#" method="post"> <table> <tr> <td><label>Product:<label> <input type="text" /></td> <td><label>Price:<label> ...

Is it possible to customize componentWillLeave(callback) in ReactCSSTransitionGroup?

I am attempting to utilize the componentWillMount hook to fade out a canvas element that is not a child of the transitioning <Home> component. The animation of the <Home> itself is functioning as expected. <ReactCSSTransitionGroup transitio ...

Personalized dropdown appearance

During my work on a select box, I discovered that custom styling is not possible. I attempted to use some plugins but did not find one that met my needs. I am seeking a dropdown menu with options in both black and gray, similar to this template but using ...

Utilizing AngularJS and ADAL.JS to Define Resource ID (Audience)

Is there a way to utilize adal.js within AngularJS to obtain a bearer token for the audience https://management.azure.com through JavaScript? I have created a client application in Azure AD and configured its permissions to allow access to the "Windows Az ...

The Step-by-Step Guide to Deselecting an Angular Checkbox with a Button

I currently have a situation where I have three checkboxes labeled as parent 1, parent 2, and parent 3. Initially, when the page loads, parent 1 and parent 3 are checked by default, while parent 2 is unchecked. However, when I manually check parent 2 and c ...

Failure to append an object to the array occurs when submitting an HTML form

I am facing an issue with a form that is supposed to add input values to an array as objects when submitted. However, every time I submit the form, the console briefly shows that there is an array with one object, only for it to disappear. Below is the f ...

The CSS style class is applied to two menus that share the same route but have different query parameters. These menus are styled with the class name

Utilizing both Vue and Vuetify version 3. For my navigation, I have implemented the v-navigation-drawer component alongside v-list for each menu item: <template> <v-navigation-drawer> <v-list nav> <v-list-item title=" ...

Limit the length of text using jQuery by specifying the maximum pixel width

Trying to utilize jQuery for a quick function that calculates the pixel width of a string on an HTML page and then shortens the string until it reaches a desired pixel width... Unfortunately, I'm encountering issues with this process as the text is n ...

Next.js - NextAuth consistently delivers a successful status code every time

In my Next.js project, I am utilizing NextAuth. The issue I'm encountering is that NextAuth consistently returns a 200 status code and updates the session to authenticated, even when the username or password doesn't match. I've attempted thr ...

Guide to sending a HTTP POST request with parameters in typescript

I need assistance sending a POST request using parameters in the following format: http://127.0.0.1:9000/api?command={"command":"value","params":{"key":"value","key":"value","key":"value","key":value,}} I attempted to do this but encountered an issue: l ...

Exploring NextJS with Typescript

Struggling to incorporate Typescript with NextJS has been a challenge, especially when it comes to destructured parameters in getInitialProps and defining the type of page functions. Take for example my _app.tsx: import { ThemeProvider } from 'styled ...

How can you use JavaScript regex to verify that the last three characters in a string are

What method can be used to confirm that a string concludes with precisely three digits? accepted examples: Hey-12-Therexx-111 001 xxx-5x444 rejected examples: Hey-12-Therexx-1111 Hey-12-Therexx-11 Hey-12-Therexx 12 112x ...

Creating dynamic captions in an Angular grid is an essential feature for enhancing the

Is there a way in Angular to dynamically update the grid titles based on an array of elements in the model? How can I display them as captions? For instance, imagine we are currently in week 202010. I would like to automatically generate the next five wee ...

When only showing the title to the client, it results in an undefined value

I have created a schema in mongoosejs that looks like this: var uploadSchema = mongoose.Schema({ title : String, happy : String, }); I am trying to show the data from my database on the client side (using ejs for templating) ...

Javascript does not function on sections generated by ajax

I'm facing an issue with a JavaScript function not working on a dynamically generated part using AJAX. Here is the AJAX call: <script> $(window).on('scroll', function() { $("#preloadmore").show(); if ($(window).height() + $(window ...

Submitting information to an HTML page for processing with a JavaScript function

I am currently working on an HTML page that includes a method operating at set intervals. window.setInterval(updateMake, 2000); function updateMake() { console.log(a); console.log(b); } The variables a and b are global variables on the HTML page. ...

jQuery sends ajax success to input type number

I am encountering an issue with the ajax success loading function when using input type number. Interestingly, when I switch the input type to text, it works perfectly fine. However, once I change the input type back to number, the loading ceases. <s ...

Challenges with unique scrollbar designs and dynamic tab loading using AJAX

Hello to all amazing members of stackoverflow, I'm facing some major challenges getting my custom scrollbar to function properly with ajax-based tabs. Any assistance you can provide would be immensely helpful. I have most of it set up and operational ...

Building a Modular Socket.io System using Express 4

I'm currently working on modularizing my application files, and I've encountered a challenge with the integration of Socket.io. My goal is to utilize io within my routes.js file. Here's an example of what I'm attempting: var router = r ...