Get 2024 Templates Mega Bundle!19 Bootstrap HTML, Vue & React Templates + 3 Vector Sets
Get for 99$

Dynamic Validation Vue Vee Validate


Hello i want to validate dynamic fields using vee validate, Fields having the same name.
For Example


<template>
<!--begin::Wrapper-->
<div class="row">
<div v-for="key in count" :key="key">
<div class="col-md-3" v-for="field in formSchema.fields" :key="field.name">
<div class="fv-row mb-10" >
<label class="form-label required" :for="field.name">{{ field.label }}</label>
<Field :as="field.as"
:id="field.id+`[${key}]`"
:name="field.name"
:class="field.class"
:key="key"
v-mask="field.mask ? field.mask : false"
/>
<ErrorMessage
:name="field.name"
class="fv-plugins-message-container invalid-feedback"
></ErrorMessage>
</div>
</div>
</div>
<div class="row">
<button
type="button" class="btn btn-lg btn-success me-3" @click="add" id="add_more_fields">
Add Location
</button>
</div>
</div>
<!--end::Wrapper-->
</template>


Text formatting options
Submit
Here's a how to add some HTML formatting to your comment:
  • <pre></pre> for JS codes block
  • <pre lang="html"></pre> for HTML code block
  • <pre lang="scss"></pre> for SCSS code block
  • <pre lang="php"></pre> for PHP code block
  • <code></code> for single line of code
  • <strong></strong> to make things bold
  • <em></em> to emphasize
  • <ul><li></li></ul>  to make list
  • <ol><li></li></ol>  to make ordered list
  • <h3></h3> to make headings
  • <a></a> for links
  • <img> to paste in an image
  • <blockquote></blockquote> to quote somebody
  • happy  :)
  • shocked  :|
  • sad  :(

Replies (4)


I have attached (step 2) and the (horizontal) vue page, is there way to validate all the dynamic fields inside the step2, I feel like Yup Object is ignoring dynamic fields



Hi Syed,

I think "Form Generator" page describes how you can validate dynamically rendered fields. See https://vee-validate.logaretm.com/v4/tutorials/dynamic-form-generator#prerequisites

Regards,
Lauris Stepanovs,
Keenthemes Support Team




<!--STEP 2 START -->



<template>
<!--begin::Wrapper-->
<div class="row">
<div v-for="key in count" :key="key">
<div class="col-md-3" v-for="field in formSchema.fields" :key="field.name+key">
<div class="fv-row mb-10" >
<label class="form-label required" :for="field.name+key">{{ field.label }}</label>
<Field :as="field.as"
:
:name="field.name+key"
:class="field.class"
:key="key"
v-mask="field.mask ? field.mask : false"
/>
<ErrorMessage
:name="field.name+key"
class="fv-plugins-message-container invalid-feedback"
></ErrorMessage>
</div>
</div>
</div>
<div class="row">
<button
type="button" class="btn btn-lg btn-success me-3" @click="add" >
Add Location
</button>
</div>
</div>
<!--end::Wrapper-->
</template>

<script lang="ts">
import { defineComponent,computed } from "vue";
import { Field, ErrorMessage } from "vee-validate";
import {mask} from "vue-the-mask"
import { useStore } from "vuex";
import { useRouter } from "vue-router";
import { Actions } from "@/store/enums/StoreEnums";
import { Mutations } from "@/store/enums/StoreEnums";
import * as Yup from "yup";

export default defineComponent({
name: "step-2",
components: {
Field,
ErrorMessage,
},
directives: {
mask: (el, binding) => {
if (!binding.value) {
return;
}
mask(el, binding);
}
},
setup () {

},
data: function () {
const count = 1;
const formSchema = {
fields: [
{
label: "Shipper Contact Person",
name: `shipper_contact_person`,
id: `shipper_contact_person`,
as: "input",
class: "form-control form-control-lg form-control-solid",

},
{
id: `shipper_phone_number`,
label: "Shipper Phone Number",
name: "shipper_phone_number",
class: "form-control form-control-lg form-control-solid",
as: "input",
mask:"####-#######",

},
{
id: `shipper_email`,
label: "Shipper Email Address",
name: `shipper_email`,
class: "form-control form-control-lg form-control-solid",
as: "input",

},
{
id: `shipper_city`,
label: "Shipper City",
name: `shipper_city`,
class: "form-control form-control-lg form-control-solid",
as: "input",

},
{
id: `shipper_address`,
label: "Shipper Address",
name: `shipper_address`,
class: "form-control form-control-lg form-control-solid",
as: "textarea",

},
{
id: `shipper_brand_name`,
label: "Brand Name",
name: `shipper_brand_name`,
class: "form-control form-control-lg form-control-solid",
as: "input",

},
{
id: `shipper_cnic`,
label: "CNIC#",
name: `shipper_cnic`,
class: "form-control form-control-lg form-control-solid",
as: "input",
mask : "#####-#######-#"
},
],
};
return {
count,
values: {},
formSchema,
}
},
methods: {
add: function(){
this.count++;
},
remove: function () {
this.count--;
},
submit: function(){
// for (var key of Object.keys(this.values)) {
// console.log(key + " -> " + this.values[key])
// }
}


}
});
</script>

<!--STEP 2 END -->




<!--HORIZONTAL VUE START -->

<template>
<!--begin::Card-->
<div class="separator my-2"></div>
<div class="mb-10 text-center">
<!--begin::Title-->
<h1 class="text-dark mb-3">Sign Up</h1>
<!--end::Title-->
<!--begin::Link-->
<div class="text-gray-400 fw-semobold fs-4">
Already have an account?

<router-link to="/sign-in" class="link-primary fw-bold">
Sign in here
</router-link>
</div>
<!--end::Link-->
</div>
<div class="card">
<!--begin::Card body-->
<div class="card-body">
<!--begin::Stepper-->
<div
class="stepper stepper-links d-flex flex-column"

ref="horizontalWizardRef"
>
<!--begin::Nav-->
<div class="stepper-nav py-5 mt-5">
<!--begin::Step 1-->
<div class="stepper-item current" data-kt-stepper-element="nav">
<h3 class="stepper-title">Profile Information
</div>
<!--end::Step 1-->

<!--begin::Step 2-->
<div class="stepper-item" data-kt-stepper-element="nav">
<h3 class="stepper-title">Shipping Information
</div>
<!--end::Step 2-->

<!--begin::Step 3-->
<div class="stepper-item" data-kt-stepper-element="nav">
<h3 class="stepper-title">Banking Information
</div>

<!--end::Step 3-->

<!--begin::Step 4-->
<div class="stepper-item" data-kt-stepper-element="nav">
<h3 class="stepper-title">Documents & Legal
</div>
<!--end::Step 4-->

<!--begin::Step 5-->
<div class="stepper-item" data-kt-stepper-element="nav">
<h3 class="stepper-title">Login Information
</div>
<!--end::Step 5-->
</div>
<!--end::Nav-->

<!--begin::Form-->
<form
class="mx-auto mw-600px w-100 pt-15 pb-10"
novalidate="novalidate"

@submit="handleStep"
>
<!--begin::Step 1-->
<div class="current" data-kt-stepper-element="content" >
<Step1></Step1>
</div>
<!--end::Step 1-->

<!--begin::Step 2-->
<div data-kt-stepper-element="content" >
<Step2></Step2>
</div>
<!--end::Step 2-->

<!--begin::Step 3-->
<div data-kt-stepper-element="content" >
<Step3></Step3>
</div>
<!--end::Step 3-->

<!--begin::Step 4-->
<div data-kt-stepper-element="content" >
<Step4></Step4>
</div>
<!--end::Step 4-->

<!--begin::Step 5-->
<div data-kt-stepper-element="content" >
<Step5></Step5>
</div>
<!--end::Step 5-->

<!--begin::Actions-->
<div class="d-flex flex-stack pt-15">
<!--begin::Wrapper-->
<div class="mr-2">
<button
type="button"
class="btn btn-lg btn-light-primary me-3"
data-kt-stepper-action="previous"
@click="previousStep"
>
<span class="svg-icon svg-icon-4 me-1">
<inline-svg src="media/icons/duotune/arrows/arr063.svg" />
</span>
Back
</button>
</div>
<!--end::Wrapper-->

<!--begin::Wrapper-->
<div>
<button
type="button"
class="btn btn-lg btn-primary me-3"
data-kt-stepper-action="submit"
v-if="currentStepIndex === totalSteps - 1"
@click="formSubmit()"
>
<span class="indicator-label">
Submit
<span class="svg-icon svg-icon-3 ms-2 me-0">
<inline-svg src="media/icons/duotune/arrows/arr064.svg" />
</span>
</span>
<span class="indicator-progress">
Please wait...
<span
class="spinner-border spinner-border-sm align-middle ms-2"
></span>
</span>
</button>

<button v-else type="submit" class="btn btn-lg btn-primary">
Continue
<span class="svg-icon svg-icon-4 ms-1 me-0">
<inline-svg src="media/icons/duotune/arrows/arr064.svg" />
</span>
</button>
</div>
<!--end::Wrapper-->
</div>
<!--end::Actions-->
</form>
<!--end::Form-->
</div>
<!--end::Stepper-->
</div>
<!--end::Card body-->
</div>
<!--end::Card-->
</template>

<script lang="ts">
import { computed, defineComponent, onMounted, ref } from "vue";
import { StepperComponent } from "@/assets/ts/components";
import { useForm } from "vee-validate";
import Swal from "sweetalert2/dist/sweetalert2.min.js";
import * as Yup from "yup";
import Step1 from "@/components/wizard/steps/Step1.vue";
import Step2 from "@/components/wizard/steps/Step2.vue";
import Step3 from "@/components/wizard/steps/Step3.vue";
import Step4 from "@/components/wizard/steps/Step4.vue";
import Step5 from "@/components/wizard/steps/Step5.vue";


interface IStep1 {
contact_name: string;
contact_person: string;
phone_no : string;
phone_no2 : string;
address : string;
cnic : string
city : string
ntn_no : string
url : string
account_type : string
reference_type : string
sale_person : string
}

interface IStep2 {
shipper_contact_person : string;
shipper_phone_number : string;
shipper_email : string;
shipper_city : string;
shipper_address : string;
shipper_brand_name : string;
shipper_cnic : string;
}

interface IStep3 {
businessName: string;
businessDescriptor: string;
businessType: string;
businessDescription: string;
businessEmail: string;
}

interface IStep4 {
nameOnCard: string;
cardNumber: string;
cardExpiryMonth: string;
cardExpiryYear: string;
cardCvv: string;
saveCard: string;
}

interface CreateAccount extends IStep1, IStep2, IStep3, IStep4 {}

export default defineComponent({
name: "kt-horizontal-wizard",
components: {
Step1,
Step2,
Step3,
Step4,
Step5,
},
setup() {
const _stepperObj = ref<StepperComponent | null>(null);
const horizontalWizardRef = ref<HTMLElement | null>(null);
const currentStepIndex = ref(0);
const formData = ref<CreateAccount>({
contact_name: "Contact Name",
contact_person: "Contact Person",
phone_no: "Phone Number",
phone_no2: "Phone Number 2",
address: "Address",
city : "City",
cnic : "CNIC#",
ntn_no : "NTN #",
url : "URL",
account_type : "Account Type",
reference_type : "Reference No#",
sale_person : "Sale Person",

shipper_contact_person : "Shipper Contact Person",
shipper_phone_number : "Shipper Phone Number",
shipper_email : "Shipper Email",
shipper_city : "Shipper City",
shipper_address : "Shipper Address",
shipper_brand_name : "Shipper Brand Name",
shipper_cnic : "Shipper CNIC",

businessName: "Keenthemes Inc.",
businessDescriptor: "KEENTHEMES",
businessType: "1",
businessDescription: "",
businessEmail: "corp@support.com",
nameOnCard: "Max Doe",
cardNumber: "4111 1111 1111 1111",
cardExpiryMonth: "1",
cardExpiryYear: "2",
cardCvv: "123",
saveCard: "1",
});

onMounted(() => {
_stepperObj.value = StepperComponent.createInsance(
horizontalWizardRef.value as HTMLElement
);
});

const createAccountSchema = [
Yup.object({
contact_name: Yup.string().required(),
contact_person: Yup.string().required(),
phone_no: Yup.string().required(),
phone_no2: Yup.string().required(),
address: Yup.string().required(),
city: Yup.string().required(),
cnic: Yup.string().required().min(15),
ntn_no : Yup.string().required(),
url : Yup.string().required(),
account_type : Yup.string().required(),
reference_type : Yup.string().required(),
sale_person : Yup.string().required(),

}),
Yup.object({
shipper_contact_person : Yup.string().required(),
shipper_phone_number : Yup.string().required(),
shipper_email : Yup.string().required(),
shipper_city : Yup.string(),
shipper_address : Yup.string(),
shipper_brand_name : Yup.string() ,
shipper_cnic : Yup.string(),
}),
Yup.object({
businessName: Yup.string().required().label("Business Name"),
businessDescriptor: Yup.string()
.required()
.label("Shortened Descriptor"),
businessType: Yup.string().required().label("Corporation Type"),
businessEmail: Yup.string().required().label("Contact Email"),
}),
Yup.object({
nameOnCard: Yup.string().required().label("Name On Card"),
cardNumber: Yup.string().required().label("Card Number"),
cardExpiryMonth: Yup.string().required().label("Expiration Month"),
cardExpiryYear: Yup.string().required().label("Expiration Year"),
cardCvv: Yup.string().required().label("CVV"),
}),
];

const currentSchema = computed(() => {
return createAccountSchema[currentStepIndex.value];
});

const { resetForm, handleSubmit } = useForm<
IStep1 | IStep2 | IStep3 | IStep4
>({
validationSchema: currentSchema,
});

const totalSteps = computed(() => {
if (!_stepperObj.value) {
return;
}

return _stepperObj.value.totatStepsNumber;
});

const handleStep = handleSubmit((values) => {
// resetForm({
// values: {
// ...formData.value,
// },
// });

console.log(formData.value);
for (const item in values) {
// eslint-disable-next-line no-prototype-builtins
if (values.hasOwnProperty(item)) {
if (values[item]) {
formData.value[item] = values[item];
}
}
}

currentStepIndex.value++;

if (!_stepperObj.value) {
return;
}

_stepperObj.value.goNext();
});

const previousStep = () => {
if (!_stepperObj.value) {
return;
}

currentStepIndex.value--;

_stepperObj.value.goPrev();
};

const formSubmit = () => {
Swal.fire({
text: "All is cool! Now you submit this form",
icon: "success",
buttonsStyling: false,
confirmButtonText: "Ok, got it!",
customClass: {
confirmButton: "btn fw-semobold btn-light-primary",
},
}).then(() => {
window.location.reload();
});
};

return {
horizontalWizardRef,
previousStep,
handleStep,
formSubmit,
totalSteps,
currentStepIndex,
};
},
});
</script>

<!--HORIZONTAL VUE END-->



Hi Syed,

The name attribute value should be unique for each field.

You can use your key variable to make name value unique and then use the name for validation.

:name="`${field.name}-${key}`"


Regards,
Lauris Stepanovs,
Keenthemes Support Team


Text formatting options
Submit
Here's a how to add some HTML formatting to your comment:
  • <pre></pre> for JS codes block
  • <pre lang="html"></pre> for HTML code block
  • <pre lang="scss"></pre> for SCSS code block
  • <pre lang="php"></pre> for PHP code block
  • <code></code> for single line of code
  • <strong></strong> to make things bold
  • <em></em> to emphasize
  • <ul><li></li></ul>  to make list
  • <ol><li></li></ol>  to make ordered list
  • <h3></h3> to make headings
  • <a></a> for links
  • <img> to paste in an image
  • <blockquote></blockquote> to quote somebody
  • happy  :)
  • shocked  :|
  • sad  :(
Text formatting options
Submit
Here's a how to add some HTML formatting to your comment:
  • <pre></pre> for JS codes block
  • <pre lang="html"></pre> for HTML code block
  • <pre lang="scss"></pre> for SCSS code block
  • <pre lang="php"></pre> for PHP code block
  • <code></code> for single line of code
  • <strong></strong> to make things bold
  • <em></em> to emphasize
  • <ul><li></li></ul>  to make list
  • <ol><li></li></ol>  to make ordered list
  • <h3></h3> to make headings
  • <a></a> for links
  • <img> to paste in an image
  • <blockquote></blockquote> to quote somebody
  • happy  :)
  • shocked  :|
  • sad  :(