Is there a way to eliminate validation-on-blur errors triggered by onBlur events?

I am currently working on a v-text-field that has the capability to handle simple math expressions like 1+1 and display the correct result (2) when the user either presses enter or moves away from the text field. Here's the code I have implemented so far:

<template>
  <v-text-field
    :rules="rules"
    @blur="compute"
    @keydown.enter="compute"
    v-model="localValue"
    validate-on-blur
  />
</template>

<script>
import { create, all } from 'mathjs'
const math = create(all)

export default {
    name: "NumericTextField",
    props: ["value"],
    data () {
        return {
            localValue: this.value,
        }
    },
    watch: {
        value (v) {
            this.localValue = v
        },
    },
    methods: {
        compute () {
            try {
                const result = math.evaluate(this.localValue)
                this.$emit("input", result)
            } catch (e) {
                console.log("compute error", e)
            }
        },
    },
    computed: {
        rules () {
                return [v => /^([0-9]*[.])?[0-9]+$/.test(v) || "Must be numeric."]
        },
    },
}
</script>

One issue I'm facing is that upon moving away from the text field, such as by tabbing to another input, the validation triggered by validate-on-blur conflicts with the @blur event triggering the computation. This results in a validation error indicating that the math expression entered is not numeric, even though the correct result appears momentarily. This behavior is not ideal. For example, entering "1+1" displays "2" but also triggers an error stating that "1+1" is not a valid number.

I experimented with solutions, including tying into the form of the page and manually revalidating all forms by referencing them using this.$refs.myForm.validate() at the end of the compute method. However, this approach compromises reusability and could become resource-intensive if there are multiple instances of this component on a single page.

Is there a way to effectively manage this race condition? Any potential workarounds or solutions would be greatly appreciated.

Answer №1

Preventing Vuetify's validate-on-blur from running first seems impossible, but there is a workaround available. Here's how you can achieve this with a sneaky workaround. Modify your template as follows:

<template>
  <v-text-field
    :rules="rules"
    @blur="validate"
    @keydown.enter="validate"
    @focus="clearRules"
    @input="clearRules"
    v-model="localValue"
  />
</template>

Since you won't be using validate-on-blur, you must manually code the setting and clearing of rules to prevent immediate application on input. Start by defining a data property with an empty array:

data() {
  return {
    rules: []
  }
},

The rules will be cleared every time the field is focused or input occurs. All that remains is to call a validate method on every blur/keydown event, which will: 1) set the rules, and 2) compute the result:

validate() {
  this.setRules();
  this.compute();
},
setRules() {
  this.rules = [v => /^([0-9]*[.])?[0-9]+$/.test(v) || "Must be numeric."];
},
compute() {
  try {
    const result = math.evaluate(this.localValue)
    this.$emit("input", result)
  } catch(e) {
    console.log("compute error", e)
  }
},

Check out the working demo below (using eval):

new Vue({
  el: '#app',
  vuetify: new Vuetify(),
  data() {
    return {
      // ...
      rules: []
    }
  },
  methods: {
    validate() {
      this.setRules();
      this.compute();
    },
    setRules() {
      this.rules = [v => /^([0-9]*[.])?[0-9]+$/.test(v) || "Must be numeric."];
    },
    compute() {
      try {
        this.localValue = eval(this.localValue);
      } catch(e) {
        // console.log("compute error", e)
      }
    },
    clearRules() {
      this.rules = [];
    }
  }
})
<div id="app">
  <v-app>
    <v-text-field
      :rules="rules"
      @blur="validate"
      @keydown.enter="validate"
      @focus="clearRules"
      @input="clearRules"
      v-model="localValue"
      ></v-text-field>
  </v-app>
</div>



<!-- LIBRARIES -->
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/@mdi/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="47212829330773693f">[email protected]</a>/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="4e383b2b3a2728370e7c6036">[email protected]</a>/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="cbbdbeae8bf9e5b3">[email protected]</a>/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c8bebdadbca1aeb188fae6b0">[email protected]</a>/dist/vuetify.js"></script>

Inspired by this source and customized for use with blur.

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

Using Vue.js to Authenticate Users with JWT Tokens Sent in Registration Emails

Hey everyone, I could really use some assistance with JWT tokens. I created a registration form using Vue.js and sent the data to the database using axios. Now, I need help figuring out how to save the token I receive in the confirmation email so that I ca ...

Problem encountered with the JavaScript for loop failing to execute consistently on each iteration

Currently, I am working on a JavaScript code that alerts the count in an array of pages. The variable urls represents an array of page names, while count contains the count value. My goal is to alert the count value for each page in the urls array. Howe ...

In the realm of Typescript Angular, transferring the value of an object's property to another property within the

I'm working with a large TypeScript object and I am hoping to automate certain parts of it to streamline my workflow. myObject = [ { id: 0, price: 100, isBought: false, click: () => this.buyItem(100, 0) } buyItem (it ...

Using AngularJS to filter JSON data

Greetings! I possess the following JSON data: $scope.Facilities= [ { Name: "-Select-", Value: 0, RegionNumber: 0 }, { Name: "Facility1", Value: 1, RegionNumber: 1 }, { Name: ...

Unable to properly test the functionality of the material-ui select component due to an error being thrown stating that the function is not being called

I've been utilizing the material-ui select component in my project and am currently writing tests for it. However, I've encountered an issue regarding testing the onChange event of the component. Here's a snippet of the code for my component ...

Employing the power of JavaScript to enable the seamless toggle of an overlay

I have a div named "navbar_menu". On clicking this div, I want the visibility of the div named "nav_overlay" to fade in. Upon another click, I want it to fade back and become invisible again. Currently, I have set the div 'nav_overlay" to have ' ...

I need help converting the "this week" button to a dropdown menu. Can someone assist me in troubleshooting what I am missing?

Seeking assistance with customizing the "this week" button on the free admin dashboard template provided by Bootstrap 4. Looking to turn it into a dropdown feature but unable to achieve success after two days of research and watching tutorials. See code sn ...

Incorporate an object property value into an established Angular/Node app by using the syntax " :12 " instead of just " 12 "

My current project is an Angular/Node MEAN stack application, but my primary concern revolves around JavaScript. When I receive a response object, it includes an SQL identity id console.log(response.recordset[0]); The output is "":12 I want to assign t ...

Understanding Vue.js props parameters

Can VueJs pass props as functions? <template> <line-chart class="card-content" :chartData="lineData2('Temp')" :options="options" :width="800"> </line-chart> </template> Is it possible to use t ...

Having a parameter that contains the characters '&' and '&' can potentially disrupt an AJAX call

Even though there is a similar question here: Parameter with '&' breaking $.ajax request, the solutions provided do not apply to my specific issue. This is because both the question and answers involve jQuery, which I am not familiar with. I ...

Achieving VueJS reactivity by initializing a variable within the mounted function

I am facing an issue with a dynamic component that builds multiple select elements. Here is the template code: <template> <div> <b-field v-for="(key,index) in allSelects" :key="index" :label=" ...

Create a visual representation of an item within a framework using an Angular directive

I am interested in using a directive to draw a triangle above a series of div elements. In my scenario, I have four squares and two values: charge and normal. The value of charge determines the color of the squares, while normal is used for drawing the t ...

Tips for transferring canvas information from JavaScript to Django using Ajax

Currently, I'm developing a Django application that allows users to activate their webcams and capture photos. These images are stored in a canvas, and my goal is to send this image to Django views so that it can be saved on the server. To trigger th ...

Choosing the Laravel 6 option for editing via AJAX: A step-by-step guide

I am looking to update a user who resides in a specific state within a country. The country and state fields are dropdown select options, with a relationship established between them and the user. The state field is populated based on the selected country. ...

issue encountered when filling out a dropdown menu using a JSON data structure

Seeking assistance with populating a button dropdown in angularjs. Encountering the error message: "Unexpected end of expression: data.WotcSummary "|. Any ideas on what might be causing this issue? Here is the JavaScript file code snippet: WotcDashBoard ...

Incorporate the Element UI DatePicker into a custom button within the Vue FullCalendar

With the power of jQuery, we have the ability to easily manipulate the Document Object Model (DOM) in order to customize the view rendering process. This allows us to add additional DOM elements or actions to existing HTML elements. $('#calendar&apos ...

Creating a string specifically for implementing regular expressions in JavaScript

I'm currently working on a custom jQuery plugin known as jQuery-Faker. This plugin is designed to produce fake data for populating form fields based on their respective field names. One of the tasks I have set out to accomplish is generating phone num ...

Why is it not possible to declare an interface or type within a TypeScript class?

I am struggling to define interface | type within a TypeScript class. Here is the code snippet: class MyClass { interface IClass { name: string, id: string } } However, I keep encountering this error: Unexpected token. A constructo ...

Looking to set an object value as optional in JavaScript?

Hello, I am currently in the process of developing a web application using ReactJS with Auth0 for user authentication. In order to update user information on my backend, I am utilizing state to store the necessary data. My challenge lies in allowing eith ...

Send form data when opening a fresh page with Javascript

In the WordPress build for our company, there is a need to transfer data when previewing a page. To streamline this process, my boss wants to override the default functionality of the preview button by opening a new tab and passing the necessary data throu ...