Utilize multiple parameters in custom validation rules in Vue 3 with the help of vuelidate

I have a requirement for two fields named "price" and "max_price". Whenever I modify the "price" field, I need a validator to trigger the lessThanMaxPrice validation rule.

Currently, everything is functioning as expected with this setup:

<script setup lang="ts">

const lessThanMaxPrice = (price: number) => {
    const maxPrice = editItemForm.max_price;

    let isValid = true;

    if (price || maxPrice) {
        if (!maxPrice) {
            isValid = false;
        } else if (price && price >= maxPrice) {
            isValid = false;
        }
    }

    return isValid;
};

const editItemRules = computed(() => {
    return {
        price: {
            lessThanMaxPrice: helpers.withMessage(t('validation_errors.price_error'), lessThanMaxPrice),
        },
   }
});


let editItemForm = reactive({
    price: number|null,
    max_price: number|null
});

const editItemV$ = useVuelidate(editItemRules, editItemForm);

</script>

<template>
<v-text-field variant="outlined" hide-details="auto" id="p" type="number"
                        :valid="editItemV$.price.$error" :color="editItemV$.price.$error ? 'success' : ''"
                        :error-messages="editItemV$.price.$error ? editItemV$.price.$errors[0].$message.toString() : ''"
                        step="0.01" @change="editItemV$.price.$touch" v-model="editItemForm.price" />

<v-text-field variant="outlined" hide-details="auto" id="max_price" type="number"
                        :valid="editItemV$.max_price.$error" :color="editItemV$.max_price.$error ? 'success' : ''"
                        :error-messages="editItemV$.max_price.$error ? editItemV$.max_price.$errors[0].$message.toString() : ''"
                        step="0.01" @change="editItemV$.max_price.$touch" v-model="editItemForm.max_price" />

</template>

Now, my goal is to move the lessThanMaxPrice function into a ValidationHelpers class so that it can be used in other components as well:

export class ValidationHelpers {
    static lessThanMaxPrice(price: number | null, maxPrice: number | null) {
        let isValid = true;

        if (price || maxPrice) {
            if (!maxPrice) {
                isValid = false;
            } else if (price && price >= maxPrice) {
                isValid = false;
            }
        }

        return isValid;
    };
}

I am struggling with how to call the ValidationHelpers.lessThanMaxPrice function with parameters. The following method is not working:

const editItemRules = computed(() => {
    return {
        price: {
            lessThanMaxPrice: (value) => helpers.withMessage(t('validation_errors.price_error'), ValidationHelpers.lessThanMaxPriceTest(value, editItemForm.max_price)),
        }
   }
});

An error is thrown by VSCode:

Argument of type 'boolean' is not assignable to parameter of type 'ValidationRule<unknown>'.ts(2345)

As I'm new to Vue / Vuelidate / Vuetify / TypeScript, your understanding and guidance are highly appreciated :)

Answer №1

It's a common scenario where the answer comes to you once you've posed the question.

I made a simple modification by changing the @change handler to @input and @blur.

<v-text-field variant="outlined" hide-details="auto" id="price" type="number"
                        :valid="editItemV$.price.$error" :color="editItemV$.price.$error ? 'success' : ''"
                        :error-messages="editItemV$.price.$error ? editItemV$.price.$errors[0].$message.toString() : ''"
                        step="0.01" @input="editItemV$.price.$touch" @blur="editItemV$.price.$touch"
                        v-model="editItemForm.price" />

The issue primarily lied within my rules setup. Following this adjustment, everything fell into place:

const editItemRules = computed(() => {
    return {
        price: {
            lessThanMaxPrice: helpers.withMessage(t('validation_errors.price_error'), (value: number | null) => ValidationHelpers.lessThanMaxPrice(value, editItemForm.max_price)),
        },
   }
});

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

Guide on incorporating an SVG file according to the user's role within an Angular application

How can I dynamically import an SVG file based on the user's role, whether they are an admin or a regular user? Currently, my code in layout.ts looks like this: <div class="layout-body h-100 "> <ng-container [ngTemplateOutlet]=&q ...

Create an Interactive Form Generator in Angular

I'm currently working on an Angular project that involves Dynamic Inputs. When I click on a button, new inputs are created and now I want to use FormBuilder to get the data. However, I am unsure of how to go about this. Although I am familiar with us ...

Can you provide a guide on setting up and utilizing mathlive within NuxtJS?

Can anyone assist me? I am trying to figure out why my code is not working or if I have implemented it incorrectly. I used npm i mathlive to obtain input. However, following the instructions for implementing nuxt plugins in the documentation has not yield ...

I encountered an eslint error when I was trying to configure Vue 3 + Quasar with a Firebase config.ts file. The error stated that there was an unsafe assignment of an `

Recently, I set up a new Vue 3 project with Quasar using the Quasar CLI. In order to store my firebase configuration, I created a new file called src/firebase/config.ts, which looks like this: // Import necessary functions from SDKs import { initializeApp ...

The React Quill interface is unable to load due to an undefined window

I recently integrated React Quill into my Next.js project and everything was functioning properly. However, I encountered an issue when attempting to incorporate ImageResize into the editor. Upon adding the line Quill.register('modules/imageResize&ap ...

Ways to receive one of two variations

Dealing with different cases for type is my current challenge. In a React Functional Component, I have a callback function property that accepts an argument of either string or number. interface InputProps { getValue?: (value: string | number) => vo ...

Utilizing an object's value as a key for a separate object

Here's an overview of my current object structure: import { imageOne, imageTwo } from "./images"; export const imageKeyMap = { "one": imageOne, "two": imageTwo } The definitions for imageOne and imageTwo ...

What is the best way to determine the data type of one property in an array of objects based on another property

I have been working on creating a straightforward parser that relies on rules provided by the constructor. Everything seems to be running smoothly, but there are some issues with data types. interface RuleBase { parse(text: string, params: Record<stri ...

Angular location services

I'm experiencing some difficulties with the geolocation feature. It works fine when the user clicks allow, but there's an issue when using If else. If the user clicks deny, it doesn't insert into the else block. You can check out this DEMO f ...

Prisma Remix is throwing a TypeError: "The function (0, import_prisma.createNote) is not defined as a function."

In my project, I wrote a function using the prisma client which is being called from the notes.tsx route in remix. export async function createNote(entity: { title: string, description: string }) { const note = await prisma.note.create({ data: ...

Using @Input to pass data from a parent component to a

Looking to modularize the form code into a separate component for reusability? Consider using @Input and referencing it in the HTML to pass values to the post method. Here's how you can achieve this: Previously, everything worked smoothly when all th ...

Implementing multiple route parameters in Angular 6

I have set up two parameterized routes for handling mails. { path: 'mails', component: MailsComponent, canActivate: [AuthGuard] }, { path: 'mails/:label', component: MailsComponent, canActivate: [AuthGuard] }, { path: 'mails/fol ...

The error message thrown is: "Unable to assign value to property 'formGroup' as it is not defined

There's a particular component structure as shown below: import { Component, Input } from '@angular/core'; import { WorkingHours } from '../../../../../hours'; import { FormGroup } from '@angular/forms'; @Component({ ...

Can a type be referenced using the generic name?

My selection includes: export type DocumentType = | Item | List | User export type DocumentInputType = | ItemInputType | ListInputType | UserInputType I want to develop a feature that can determine the input type based on the document type wi ...

Access User Authentication Profile Information in Firebase Utilizing Angular 2

Need assistance with retrieving user profile information from Angularfire Authentication in Angular? Specifically looking to access the user's Facebook profile picture and name. Your help would be greatly appreciated. Thank you! I have attempted the ...

Issue with Radio Button Value Submission in Angular 6 and Laravel 5.5

I developed a CRUD application utilizing Angular and Laravel 5.5. Within this application, I included three radio buttons, but encountered an error when trying to retrieve their values... A type error occurred indicating it was unable to read the data t ...

TSConfig - Automatically Generates a ".js" File for Every ".ts" File

Having a unique software application with an unconventional file structure project ├── tsconfig.json ├── app_1 │ ├── ts │ └── js | └── app_2 ├── ts └── js I aim to compile files located inside the ...

Obtain a particular column from a JSON document using Angular 2

Currently, I am working on a project in Angular2 that requires the use of an online JSON file. I have utilized http.get to retrieve the file, but I only need the data from the second and third columns which contain the first name and last name. If you wan ...

Optimizing TypeScript/JavaScript for both browser and Node environments through efficient tree-shaking

I am currently tackling a TypeScript project that includes multiple modules shared between a browser client and a Node-based server. Our goal is to bundle and tree-shake these modules using webpack/rollup for the browser, but this requires configuring the ...

Understanding the Behavior of Vue 3's setInterval Methods

Environment I am working on a Vue 3 Application where I need to run a constant setInterval() in the background (Game Loop). To achieve this, I have placed the code in store/index.js and invoked it from views/Playground.vue's mounted() lifecycle hook ...