Ensuring validity with Vuelidate for customizable fields

There's a form where fields are dynamically added on a click event. I want a validation error to appear when the field value is less than 9 digits after changing or blurring it. The issue is that since the fields are created dynamically with the same v-model, the rule applies to all of them. How can I make it so that it only affects the one the user is currently interacting with? Initially, the screen loads with 10 fields, and more can be added later. While filling out the first 10 fields, I don't want a validation message to pop up after the 5th one fails, affecting all subsequent fields.

Below is a simplified version of the code:

<template>
    <div>
        <div>
            <button @click="onAddBarcodes">Add More</button>
        </div>
        <div v-for="(barcode, index) in barcodes" :key="index">
            <div>
                <div>
                    <label>Starting Roll #:</label>
                    <input
                        name="startbarcoderoll"
                        maxlength="9"
                        v-model.trim="$v.barcode.barcodeStart.$model"
                        :id="barcode.id"
                        ref="bcentry"
                    />
                    <!-- max length message -->
                    <div v-if="!$v.barcode.barcodeStart.minLength">
                        <span
                            v-if="!$v.barcode.barcodeStart.minLength"
                        >App Barcode must be exactly {{$v.barcode.barcodeStart.$params.minLength.min}} characters.</span>
                    </div>
                </div>
                <button @click="onDeleteBarcodes(barcode.id)">Remove</button>
            </div>
        </div>
    </div>
</template>

<script>
const { minLength } = require("vuelidate/lib/validators");

export default {
    data() {
        return {
            barcodes: [],
            barcode: {
                barcodeStart: ""
            }
        };
    },
    validations: {
        barcode: {
            barcodeStart: {
                minLength: minLength(9)
            }
        }
    },
    methods: {
        scanBarcodeNumber(value) {
            this.barcode.barcodeStart = value;
            this.$v.barcode.barcodeStart.$touch();
        },

        onAddBarcodes() {
            const newBarcode = {
                id: Math.random() * Math.random() * 1000,
                barcodeStart: ""
            };
            this.barcodes.push(newBarcode);
        },
        onDeleteBarcodes(id) {
            this.barcodes = this.barcodes.filter(barcode => barcode.id !== id);
        }
    }
};
</script>

Here's a visual illustration of the problem:

Note: Vuelidate is installed globally within Vue for use across multiple components, which explains why it's not directly featured in this specific code snippet.

https://i.stack.imgur.com/ROZjE.png https://i.stack.imgur.com/xdOPD.png

Answer №1

Implement dynamic validations by using the validations function and adding a unique validation for each individual barcode.

Replace $v.barcode with $v[`barcode-${index}`] for each field:

<template>
    <div>
        <div>
            <button @click="onAddBarcodes">Add More</button>
        </div>
        <div v-for="(barcode, index) in barcodes" :key="index">
            <div>
                <div>
                    <label>Starting Roll #:</label>
                    <input
                        name="startbarcoderoll"
                        maxlength="9"
                        v-model.trim="$v[`barcode-${index}`].barcodeStart.$model"
                        :id="barcode.id"
                        ref="bcentry"
                    />
                    <!-- max length message -->
                    <div v-if="!$v[`barcode-${index}`].barcodeStart.minLength">
                        <span
                            v-if="!$v[`barcode-${index}`].barcodeStart.minLength"
                        >App Barcode must be exactly {{$v[`barcode-${index}`].barcodeStart.$params.minLength.min}} characters.</span>
                    </div>
                </div>
                <button @click="onDeleteBarcodes(barcode.id)">Remove</button>
            </div>
        </div>
    </div>
</template>

In your javascript section, define the validations function with the specified barcode validation for each field:

export default {
  validations() {
    const rules = {};
    this.barcodes.forEach((item, index) => {
      rules[`barcode-${index}`] = {
        barcodeStart: {
          minLength: minLength(9),
        },
      };
    });
    return rules;
  },
};

This approach may not be the most efficient, but it should accomplish what you desire.

Answer №2

If you're looking to enhance your form validation, consider implementing Vuelidate's $each feature.

To learn more, check out the documentation provided here:

For further insights, feel free to explore this informative article on the topic:

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

Iterating through an array of objects and performing reduction based on various key-value pairs

I am faced with a challenge of consolidating a large array of objects into one single array that has a specific structure. Each item, such as a banana, needs to be present in two separate objects for buy orders and sell orders, each with their own distinct ...

Fill a Bootstrap Table with information obtained from a JSON file source

My journey into the world of bootstrap and json files has hit a roadblock, and I need some help with the following issue: Here is a snippet of my code: <div class="container"> <h1 class="text text-success text-center ">Kontoauszug</ ...

Neglectful TypeScript null checks overlooking array.length verification

When TypeScript is compiled with strict null checks, the code snippet below does not pass type checking even though it appears to be correct: const arr: number[] = [1, 2, 3] const f = (n: number) => { } while (arr.length) { f(arr.pop()) } The comp ...

Unable to render Angular charts

Recently, I've been attempting to integrate angular charts using the chart.js bundle sourced from CDN links. The version of Angular being used is 1.5.7 and for chart.js it's 2.1.6. I encountered the following error message: angular.js:13708 T ...

Guide to implementing bidirectional data binding for a particular element within a dynamic array with an automatically determined index

Imagine having a JavaScript dynamic array retrieved from a database: customers = [{'id':1, 'name':'John'},{'id':2, 'name':'Tim}, ...] Accompanied by input fields: <input type='text' na ...

React does not display the items enclosed within the map function

I am facing an issue with rendering elements from a map function. Despite trying to modify the return statement, I have not been able to resolve the issue. class API extends Component { myTop10Artists() { Api.getMyTopArtists(function (err, data) { ...

Troubles with loading images on Node.js, Express, and EJS powered Bootstrap 5 navbar

Currently, I am in the process of creating a website using express/node.js/ejs. However, I am facing challenges when it comes to constructing a navbar with Bootstrap 5.0. In my app.js file, I have included express.static: app.use(express.static('publi ...

Unable to load routes from ./app.js in the file ./src/routes/index.js

Just dipping my toes into the world of nodejs. I recently moved all my routes from app.js to a separate file located at PROJECT_DIR/src/routes/index.js. However, when I try to open the page in my browser, it displays "Cannot GET /wines". Below are snippets ...

The Ionic framework is showing an error that says "'LoginCtrl' is not defined as a function."

I encountered an issue while attempting to set up simple navigation in my ionic application. The error message I received was: "Argument 'LoginCtrl' is not a function, got undefined in the Ionic. What could be causing this problem?" Here is a sn ...

Using a responsive menu (mmenu) can lead to an increase in Cumulative Layout

I've implemented mmenu as a responsive menu on my website. Recently, I discovered errors in Google's search console related to high CLS (Cumulative Layout Shift). Upon further investigation, I noticed that when loading my page in "slow" mode for ...

When working with TypeScript, how do you determine the appropriate usage between "let" and "const"?

For TypeScript, under what circumstances would you choose to use "let" versus "const"? ...

Newbie in PHP: Techniques for transferring PHP variables between different sections of PHP code

In my project, I have a file named index.php which is responsible for uploading files to the server and setting PHP variables such as $target_folder_and_file_name. This index.php file also includes the following line (originally it was in an index.html fi ...

Show off a sleek slider within a Bootstrap dropdown menu

Is there a way to display a sleek slider within a Bootstrap dropdown element? The issue arises when the slider fails to function if the dropdown is not open from the start, and the prev/next buttons do not respond correctly. For reference, here is my curr ...

Creating an interactive API endpoint in AngularJS for a DreamFactory stored procedure just got easier with these simple steps

If I am using a factory/service to access my API in DreamFactory. FoundationApp.factory('testAPI', function($resource, ChildID) { return $resource('http://Domain.com/rest/RemoteDB/_proc/TimeLog_Checkin(:ChildID)/?app_name=App&fields ...

Having trouble with understanding the usage of "this" in nodejs/js when using it after a callback function within setTimeout

It's quite peculiar. Here is the code snippet that I am having trouble with: var client = { init: function () { this.connect(); return this; }, connect: function () { var clientObj = this; this.socket = ...

Initiate a JavaScript confirmation dialog using server-side logic in ASP.NET

Does anyone know how to troubleshoot the issue with this code? I am trying to make it so that when btnOne is clicked and a is true, a confirm box pops up. If yes is selected, then it should execute the btnTwo method. Currently, the popup isn't appeari ...

Encountering a CouchDB 401 Unauthorized Error

I have a couchDB database named "guestbook". Initially, I utilized the following code to add a user to the "_users" database: $scope.submit = function(){ var url = "https://sub.iriscouch.com/_users/org.couchdb.user:" + $scope.name; console.log(url); $ht ...

Using ThreeJS to calculate the rotation needed for one Vector3 to align with another Vector3

Recently delving into the world of ThreeJS, I've been exploring its potential for fun and creativity. My current project involves using ThreeJS in conjunction with aframe. The task at hand requires computing with ThreeJS to pass position and rotation ...

Displaying an image in AngularJS using a byte array received in the response

Dealing with a service that adds properties to a file and returns it as a byte array in the response. I'm struggling to display it properly since it's in byte form. Attempted converting it to base64 but still showing raw bytes. PNG IHDR&L ...

Using Node.js to integrate Stripe payment method

After successfully implementing a stripe payment method with node and express, I encountered some issues. Although the payment runs smoothly and returns a success message, the customer is not being added to the list of stripe customers. Additionally, my no ...