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.