Ways to verify a single field within a Zod schema individually rather than the entire schema

I am currently working on a form that consists of multiple inputs, including 'hours' and 'price'. The technology stack I am using is NextJS along with server-side actions. When a user clicks the submit button, here's what happens:

  • The entire form is validated on the client side using Zod.
  • If the validation is successful, the data is sent to the server for further validation and database mutation.

Specifically, the 'hours' input should be between 10 and 100. Here's an example scenario that illustrates the current functionality:

  • User enters 5 in the 'hours' field
  • Clicks submit
  • Zod validates and displays the error message: 'Hours should be between 10 and 100'

While this works fine, there's an improvement I'd like to implement. I want the validation to trigger onBlur when the user enters a valid value (e.g., 50) after seeing an error message. This will prevent confusion where the input is correct but the error message persists.

My question is, how can I achieve this? Would I need to create separate schemas for each field and call onBlur?

Here is a snippet of the form implementation:

<form
    ref={formRef}
    action={async (formData) => {
        const validatedFields = validateFields(formData)

        const state = await createCard(validatedFields)
        if (state.status === 'success') {
            formRef.current?.reset()
            setOpen(false)
            setClientErrorMessage(undefined)
        } else if (state.status === 'error') {
            console.log(state)
            setserverErrorMessage(state.message)
        }
    }}
>
    // Form content goes here
</form>

And here is the function used for validating fields:

const validateFields = (formData: FormData) => {
    const validatedFields = createSchema.safeParse({
        client_id: formData.get('client_id'),
        hours: Number(formData.get('hours')),
        hours_left: Number(formData.get('hours')),
        price: Number(formData.get('price')),
        ends_at: formData.get('ends_at'),
    })

    if (!validatedFields.success) {
        return setClientErrorMessage(validatedFields.error.flatten().fieldErrors)
    }

    return validateFields
}

I would appreciate any insights on how to tackle this challenge effectively.

Answer №1

Verifying specific fields can be done using a portion of the schema before conducting a full validation with an extended schema.

Here are two methods for expanding a schema:

Referencing one schema within another

const firstSchema = z.object({
  client_id: z.number(),
  hours: z.number(),
  hours_left: z.number(),
  price: z.number(),
  ends_at: z.number()
});

const secondSchema = z.object({
  data: firstSchema,
  another_field: z.string(),
  and_another: z.object({})
});

The resulting structure of secondSchema will look like this:

{
  a: {
    client_id: number;
    hours: number;
    // etc...
  },
  another_field: string;
  and_another: {}
}

Expanding an existing schema using .extend()

const originalSchema = z.object({
  client_id: z.number(),
  hours: z.number(),
  hours_left: z.number(),
  price: z.number(),
  ends_at: z.number()
});

const extendedSchema = originalSchema.extend({
  additional_field: z.string()
});

The final shape of the extended_a will be:

{
  client_id: number;
  hours: number;
  // etc...
  additional_field: string
}

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

Exploring locations using the Google Geolocation API

I have a website and am trying to determine the location of my visitors. I came across this code on Google Code: <script type="text/javascript" src="gears_init.js"></script> <script type="text/javascript"> var geo = google.gears.factory ...

Guidelines for inputting a value into a JavaScript list and choosing a specific item within the list

When it comes to studying Selenium Web, I rely on the website. My current challenge involves inputting 'Ottawa' into the location control and then selecting 'Ottawa, ON'. WebElement el = driver.findElement( By.xpath("//*[contains( ...

The compatibility between V-model and TinyMCE is unreliable

I've been working on integrating Vuejs and TinyMCE, using the @tinymce/tinymce-vue package for the Vue integration. I followed all the instructions and everything seems to be functioning properly - I can write, insert images... everything except for t ...

Is there a way to create a button that directs to a different page, while also automatically populating a search bar with specific information?

Here we have a bootstrap dropdown menu that features various product categories. Each button should lead to a Product.html page where an Angular JS search bar is utilized. The goal is for the search bar to be pre-filled with the name of the selected button ...

Output Scalable Vector Graphics (SVG) content on a webpage

I need to include an SVG element in my Angular 2+ code. My goal is to provide users with the option to print the SVG element as it appears on the screen. <div class="floor-plan" id="printSectionId2" (drop)="onDrop($event)" (dragover)="onDragOver ...

What is the best way to implement this design using CSS or JavaScript?

I would like to enhance the appearance of my school website during these challenging times of the pandemic by adding some CSS or JavaScript elements. However, I am unsure how to go about it. ...

Updates to AngularJs models are not being reflected

I am facing an issue with my model that I want to make editable, but for some reason nothing changes - the textbox fails to appear and the model remains unchanged when using ng-view. I can confirm that the function enableEditor() is being triggered as I s ...

Provide a parameter for a function's callback

I am attempting to utilize lodash's debounce function to delay the onChange event. See the code snippet below. import React, { useState, useEffect, useCallback } from "react"; import { TopBar } from "@shopify/polaris"; import { debounce } from "lodas ...

Organize a method's for-loop using JavaScript modules

I have a function that looks like this: function createModifiedList(people){ const modifiedList = [] for (let i = 0; i < people.length; i++){ modifiedList.push({ name: person.firstName + " " + person.lastName, ...

Error: The function modal() is undefined in the jQuery library

I am trying to open a modal on page load, but I encountered the following error: jquery.min.js:2 Uncaught TypeError: $(...).modal is not a function at HTMLDocument.<anonymous> ((index):491) at j (jquery.min.js:2) at k (jquery.min.js:2) Below is th ...

Tips for achieving seamless scrolling with the combination of javascript and css

Looking for a solution to achieve smooth scrolling on an HTML page without using the #id_name to scroll to a specific div. Instead, I want to scroll to a particular point, such as having a button that scrolls down the webpage smoothly by 250px when press ...

Ways to access information from a SQLite database using Angular

I am a beginner in front-end/back-end communication and I need guidance on how to retrieve data from a SQLite db file to populate a page in my Angular project. I have no idea where to begin, so any resources you can recommend would be greatly appreciated. ...

"Encountering issues with running a MongoDB aggregate query involving date fields

I have been attempting to retrieve data from MongoDB using an aggregate query in Node.js for a specific date range. let date = '20230925' let year = date.slice(0, 4); let month = String(date.slice(4, 6)).padStart(2, '0'); ...

I am looking to have the first option in the dropdown menu appear as a placeholder text

In my form, I have two phone number fields - one for mobile phone and the other for home phone. I need to make only one of them mandatory. Can someone please advise me on how to accomplish this? ...

Retrieve the image and insert it using an img tag

Working on a project, I want to include Instagram profile pictures by embedding them. Although I have the image URL, I am struggling to integrate it into my HTML page. Take a look at this sample: This provided link displays the Instagram profile picture. ...

Utilizing jsPDF and html2canvas in a Vue.js application (no webpack involved)

I've been working on a feature within a Vuejs project that allows users to export a PDF containing specific Vuejs components by clicking a button. Everything was going smoothly until I encountered an issue. After npm installing the jsPDF and html2canv ...

How can I access the parent function within module.exports?

Hello, I am having issues with this code because I am unable to access checkIf in order to set its property LengthIs. When I log whether this is equal to module.exports, it returns false. Upon further inspection, I also checked what this was and it retur ...

Having trouble maintaining the initial state of the first accordion in a foreach loop

I have a collapsible accordion here, which is functioning well with static data. Now, I have connected it to a database and am attempting to retrieve data from the database. Below is the code I have implemented so far in CodeIgniter, View: <div class= ...

Is it possible to streamline the chaining of promises generated from MongoDB queries?

This feature allows for the display of all collections in a MongoDB database, along with the count of documents in each collection using bluebird promises. function displayMongoCollections(db) { var promises = [] db.listCollections().toArray().the ...

Experiencing Deployment Challenges with AWS Amplify for Next.js and React.js Projects

I'm facing challenges deploying my Next.js application on AWS Amplify as I consistently encounter an error during the build process. The error message highlights the absence of a package.json file, despite its presence in the project directory. After ...