Update forms page
parent
6b491f3804
commit
bb043ac053
|
@ -63,31 +63,6 @@ export default {
|
|||
),
|
||||
code: {
|
||||
basic: `
|
||||
<Fieldset legend="Schema">
|
||||
<RadioButtonGroup v-model="selectedSchema" name="schema" class="flex flex-wrap gap-4" @update:modelValue="changeResolver">
|
||||
<div class="flex items-center">
|
||||
<RadioButton inputId="zod" value="Zod" />
|
||||
<label for="zod" class="ml-2">Zod</label>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<RadioButton inputId="yup" value="Yup" />
|
||||
<label for="yup" class="ml-2">Yup</label>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<RadioButton inputId="valibot" value="Valibot" />
|
||||
<label for="valibot" class="ml-2">Valibot</label>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<RadioButton inputId="superStruct" value="SuperStruct" />
|
||||
<label for="superStruct" class="ml-2">SuperStruct</label>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<RadioButton inputId="custom" value="Custom" />
|
||||
<label for="custom" class="ml-2">Custom</label>
|
||||
</div>
|
||||
</RadioButtonGroup>
|
||||
</Fieldset>
|
||||
|
||||
<Form v-slot="$form" :initialValues :resolver @submit="onFormSubmit" class="flex flex-col gap-4 w-full sm:w-56">
|
||||
<div class="flex flex-col gap-2">
|
||||
<InputText name="username" type="text" placeholder="Username" fluid />
|
||||
|
@ -98,6 +73,9 @@ export default {
|
|||
`,
|
||||
options: `
|
||||
<template>
|
||||
<div class="card flex flex-col items-center gap-5">
|
||||
<Toast />
|
||||
|
||||
<Fieldset legend="Schema">
|
||||
<RadioButtonGroup v-model="selectedSchema" name="schema" class="flex flex-wrap gap-4" @update:modelValue="changeResolver">
|
||||
<div class="flex items-center">
|
||||
|
@ -130,6 +108,7 @@ export default {
|
|||
</div>
|
||||
<Button type="submit" severity="secondary" label="Submit" />
|
||||
</Form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@ -204,18 +183,117 @@ export default {
|
|||
`,
|
||||
composition: `
|
||||
<template>
|
||||
<Card>
|
||||
<template #title>Simple Card</template>
|
||||
<template #content>
|
||||
<p class="m-0">
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore sed consequuntur error repudiandae numquam deserunt quisquam repellat libero asperiores earum nam nobis, culpa ratione quam perferendis esse, cupiditate neque
|
||||
quas!
|
||||
</p>
|
||||
</template>
|
||||
</Card>
|
||||
<div class="card flex flex-col items-center gap-5">
|
||||
<Toast />
|
||||
|
||||
<Fieldset legend="Schema">
|
||||
<RadioButtonGroup v-model="selectedSchema" name="schema" class="flex flex-wrap gap-4" @update:modelValue="changeResolver">
|
||||
<div class="flex items-center">
|
||||
<RadioButton inputId="zod" value="Zod" />
|
||||
<label for="zod" class="ml-2">Zod</label>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<RadioButton inputId="yup" value="Yup" />
|
||||
<label for="yup" class="ml-2">Yup</label>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<RadioButton inputId="valibot" value="Valibot" />
|
||||
<label for="valibot" class="ml-2">Valibot</label>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<RadioButton inputId="superStruct" value="SuperStruct" />
|
||||
<label for="superStruct" class="ml-2">SuperStruct</label>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<RadioButton inputId="custom" value="Custom" />
|
||||
<label for="custom" class="ml-2">Custom</label>
|
||||
</div>
|
||||
</RadioButtonGroup>
|
||||
</Fieldset>
|
||||
|
||||
<Form v-slot="$form" :initialValues :resolver @submit="onFormSubmit" class="flex flex-col gap-4 w-full sm:w-56">
|
||||
<div class="flex flex-col gap-2">
|
||||
<InputText name="username" type="text" placeholder="Username" fluid />
|
||||
<Message v-if="$form.username?.invalid" severity="error">{{ $form.username.error.message }}</Message>
|
||||
</div>
|
||||
<Button type="submit" severity="secondary" label="Submit" />
|
||||
</Form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue';
|
||||
import { superStructResolver, valibotResolver, yupResolver, zodResolver } from '@primevue/form/resolvers';
|
||||
import * as s from 'superstruct';
|
||||
import * as v from 'valibot';
|
||||
import * as yup from 'yup';
|
||||
import { z } from 'zod';
|
||||
import { useToast } from 'primevue/usetoast';
|
||||
|
||||
const toast = useToast();
|
||||
|
||||
const initialValues = ref({
|
||||
username: ''
|
||||
});
|
||||
const selectedSchema = ref('Zod');
|
||||
|
||||
const resolver = ref(zodResolver(
|
||||
z.object({
|
||||
username: z.string().min(1, { message: 'Username is required via Zod.' })
|
||||
})
|
||||
));
|
||||
|
||||
watch(selectedSchema, (newSchema) => {
|
||||
changeResolver(newSchema);
|
||||
});
|
||||
|
||||
function changeResolver(schema) {
|
||||
if (schema === 'Zod') {
|
||||
resolver.value = zodResolver(
|
||||
z.object({
|
||||
username: z.string().min(1, { message: 'Username is required via Zod.' })
|
||||
})
|
||||
);
|
||||
} else if (schema === 'Yup') {
|
||||
resolver.value = yupResolver(
|
||||
yup.object().shape({
|
||||
username: yup.string().required('Username is required via Yup.')
|
||||
})
|
||||
);
|
||||
} else if (schema === 'Valibot') {
|
||||
resolver.value = valibotResolver(
|
||||
v.object({
|
||||
username: v.pipe(v.string(), v.minLength(1, 'Username is required via Valibot.'))
|
||||
})
|
||||
);
|
||||
} else if (schema === 'SuperStruct') {
|
||||
resolver.value = superStructResolver(
|
||||
s.object({
|
||||
username: s.nonempty(s.string())
|
||||
})
|
||||
);
|
||||
} else if (schema === 'Custom') {
|
||||
resolver.value = ({ values }) => {
|
||||
const errors = {};
|
||||
|
||||
if (!values.username) {
|
||||
errors.username = [{ message: 'Username is required.' }];
|
||||
}
|
||||
|
||||
return {
|
||||
errors
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function handleSubmit() {
|
||||
resolver.value({ values: initialValues.value }).then(({ valid }) => {
|
||||
if (valid) {
|
||||
toast.add({ severity: 'success', summary: 'Form is submitted.', life: 3000 });
|
||||
}
|
||||
});
|
||||
}
|
||||
<\/script>
|
||||
`
|
||||
}
|
||||
|
|
|
@ -27,8 +27,8 @@ export default {
|
|||
basic: `
|
||||
<Form v-slot="$form" :initialValues :resolver @submit="onFormSubmit" class="grid lg:grid-cols-2 gap-4 w-full">
|
||||
<div class="flex flex-col justify-center items-center gap-4">
|
||||
<InputText name="username" type="text" placeholder="Username" />
|
||||
<Button type="submit" severity="secondary" label="Submit" />
|
||||
<InputText name="username" type="text" placeholder="Username" fluid class="sm:w-56" />
|
||||
<Button type="submit" severity="secondary" label="Submit" fluid class="sm:w-56" />
|
||||
</div>
|
||||
<Fieldset legend="Form States">
|
||||
<pre class="whitespace-pre-wrap">{{ $form }}</pre>
|
||||
|
@ -37,15 +37,19 @@ export default {
|
|||
`,
|
||||
options: `
|
||||
<template>
|
||||
<Form v-slot="$form" :initialValues :resolver @submit="onFormSubmit" class="grid md:grid-cols-2 gap-4 w-full">
|
||||
<div class="card flex justify-center">
|
||||
<Toast />
|
||||
|
||||
<Form v-slot="$form" :initialValues :resolver @submit="onFormSubmit" class="grid lg:grid-cols-2 gap-4 w-full">
|
||||
<div class="flex flex-col justify-center items-center gap-4">
|
||||
<InputText name="username" type="text" placeholder="Username" />
|
||||
<Button type="submit" severity="secondary" label="Submit" />
|
||||
<InputText name="username" type="text" placeholder="Username" fluid class="sm:w-56" />
|
||||
<Button type="submit" severity="secondary" label="Submit" fluid class="sm:w-56" />
|
||||
</div>
|
||||
<Fieldset legend="Form States">
|
||||
<pre>{{ $form }}</pre>
|
||||
<pre class="whitespace-pre-wrap">{{ $form }}</pre>
|
||||
</Fieldset>
|
||||
</Form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@ -54,15 +58,19 @@ export default {
|
|||
return {
|
||||
initialValues: {
|
||||
username: ''
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
resolver: ({ values }) => {
|
||||
const errors = {};
|
||||
const errors = { username: [] };
|
||||
|
||||
if (!values.username) {
|
||||
errors.username = [{ message: 'Username is required.' }];
|
||||
errors.username.push({ type: 'required', message: 'Username is required.' });
|
||||
}
|
||||
|
||||
if (values.username?.length < 3) {
|
||||
errors.username.push({ type: 'minimum', message: 'Username must be at least 3 characters long.' });
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -80,18 +88,52 @@ export default {
|
|||
`,
|
||||
composition: `
|
||||
<template>
|
||||
<Card>
|
||||
<template #title>Simple Card</template>
|
||||
<template #content>
|
||||
<p class="m-0">
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore sed consequuntur error repudiandae numquam deserunt quisquam repellat libero asperiores earum nam nobis, culpa ratione quam perferendis esse, cupiditate neque
|
||||
quas!
|
||||
</p>
|
||||
</template>
|
||||
</Card>
|
||||
<div class="card flex justify-center">
|
||||
<Toast />
|
||||
|
||||
<Form v-slot="$form" :initialValues :resolver @submit="onFormSubmit" class="grid lg:grid-cols-2 gap-4 w-full">
|
||||
<div class="flex flex-col justify-center items-center gap-4">
|
||||
<InputText name="username" type="text" placeholder="Username" fluid class="sm:w-56" />
|
||||
<Button type="submit" severity="secondary" label="Submit" fluid class="sm:w-56" />
|
||||
</div>
|
||||
<Fieldset legend="Form States">
|
||||
<pre class="whitespace-pre-wrap">{{ $form }}</pre>
|
||||
</Fieldset>
|
||||
</Form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { useToast } from 'primevue/usetoast';
|
||||
|
||||
const toast = useToast();
|
||||
|
||||
const initialValues = ref({
|
||||
username: ''
|
||||
});
|
||||
|
||||
const resolver = ({ values }) => {
|
||||
const errors = { username: [] };
|
||||
|
||||
if (!values.username) {
|
||||
errors.username.push({ type: 'required', message: 'Username is required.' });
|
||||
}
|
||||
|
||||
if (values.username?.length < 3) {
|
||||
errors.username.push({ type: 'minimum', message: 'Username must be at least 3 characters long.' });
|
||||
}
|
||||
|
||||
return {
|
||||
errors
|
||||
};
|
||||
};
|
||||
|
||||
const onFormSubmit = ({ valid }) => {
|
||||
if (valid) {
|
||||
toast.add({ severity: 'success', summary: 'Form is submitted.', life: 3000 });
|
||||
}
|
||||
}
|
||||
<\/script>
|
||||
`
|
||||
}
|
||||
|
|
|
@ -71,6 +71,9 @@ export default {
|
|||
`,
|
||||
options: `
|
||||
<template>
|
||||
<div class="card flex justify-center">
|
||||
<Toast />
|
||||
|
||||
<Form v-slot="$form" :initialValues :resolver @submit="onFormSubmit" class="flex flex-col gap-4 w-full sm:w-56">
|
||||
<div class="flex flex-col gap-2">
|
||||
<InputText name="username" type="text" placeholder="Username" fluid />
|
||||
|
@ -86,6 +89,7 @@ export default {
|
|||
</div>
|
||||
<Button type="submit" severity="secondary" label="Submit" />
|
||||
</Form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@ -126,6 +130,8 @@ export default {
|
|||
// e.states: Contains the current state of each form field, including validity status.
|
||||
// e.errors: An object that holds any validation errors for the invalid fields in the form.
|
||||
// e.values: An object containing the current values of all form fields.
|
||||
// e.reset: A function that resets the form to its initial state.
|
||||
|
||||
if (e.valid) {
|
||||
this.$toast.add({ severity: 'success', summary: 'Form is submitted.', life: 3000 });
|
||||
}
|
||||
|
@ -136,18 +142,71 @@ export default {
|
|||
`,
|
||||
composition: `
|
||||
<template>
|
||||
<Card>
|
||||
<template #title>Simple Card</template>
|
||||
<template #content>
|
||||
<p class="m-0">
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore sed consequuntur error repudiandae numquam deserunt quisquam repellat libero asperiores earum nam nobis, culpa ratione quam perferendis esse, cupiditate neque
|
||||
quas!
|
||||
</p>
|
||||
</template>
|
||||
</Card>
|
||||
<div class="card flex justify-center">
|
||||
<Toast />
|
||||
|
||||
<Form v-slot="$form" :initialValues :resolver @submit="onFormSubmit" class="flex flex-col gap-4 w-full sm:w-56">
|
||||
<div class="flex flex-col gap-2">
|
||||
<InputText name="username" type="text" placeholder="Username" fluid />
|
||||
<Message v-if="$form.username?.invalid" severity="error">{{ $form.username.error.message }}</Message>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<Password name="password" placeholder="Password" :feedback="false" fluid />
|
||||
<Message v-if="$form.password?.invalid" severity="error">
|
||||
<ul class="mx-1 px-3">
|
||||
<li v-for="(error, index) of $form.password.errors" :key="index" class="py-1">{{ error.message }}</li>
|
||||
</ul>
|
||||
</Message>
|
||||
</div>
|
||||
<Button type="submit" severity="secondary" label="Submit" />
|
||||
</Form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { zodResolver } from '@primevue/form/resolvers';
|
||||
import { z } from 'zod';
|
||||
import { useToast } from 'primevue/usetoast';
|
||||
|
||||
const toast = useToast();
|
||||
|
||||
const initialValues = ref({
|
||||
username: '',
|
||||
password: ''
|
||||
});
|
||||
|
||||
const resolver = zodResolver(
|
||||
z.object({
|
||||
username: z.string().min(1, { message: 'Username is required.' }),
|
||||
password: z
|
||||
.string()
|
||||
.min(3, { message: 'Minimum 3 characters.' })
|
||||
.max(8, { message: 'Maximum 8 characters.' })
|
||||
.refine((value) => /[a-z]/.test(value), {
|
||||
message: 'Must have a lowercase letter.'
|
||||
})
|
||||
.refine((value) => /[A-Z]/.test(value), {
|
||||
message: 'Must have an uppercase letter.'
|
||||
})
|
||||
.refine((value) => /\d/.test(value), {
|
||||
message: 'Must have a number.'
|
||||
})
|
||||
})
|
||||
);
|
||||
|
||||
const onFormSubmit = (e) => {
|
||||
// e.originalEvent: Represents the native form submit event.
|
||||
// e.valid: A boolean that indicates whether the form is valid or not.
|
||||
// e.states: Contains the current state of each form field, including validity status.
|
||||
// e.errors: An object that holds any validation errors for the invalid fields in the form.
|
||||
// e.values: An object containing the current values of all form fields.
|
||||
// e.reset: A function that resets the form to its initial state.
|
||||
|
||||
if (e.valid) {
|
||||
toast.add({ severity: 'success', summary: 'Form is submitted.', life: 3000 });
|
||||
}
|
||||
};
|
||||
<\/script>
|
||||
`
|
||||
}
|
||||
|
@ -161,6 +220,7 @@ export default {
|
|||
// e.errors: An object that holds any validation errors for the invalid fields in the form.
|
||||
// e.values: An object containing the current values of all form fields.
|
||||
// e.reset: A function that resets the form to its initial state.
|
||||
|
||||
if (e.valid) {
|
||||
this.$toast.add({ severity: 'success', summary: 'Form is submitted.', life: 3000 });
|
||||
}
|
||||
|
|
|
@ -54,13 +54,25 @@ export default {
|
|||
`,
|
||||
options: `
|
||||
<template>
|
||||
<Form v-slot="$form" :initialValues :resolver @submit="onFormSubmit" class="flex flex-col gap-4 w-full sm:w-56">
|
||||
<div class="card flex justify-center">
|
||||
<Toast />
|
||||
|
||||
<Form v-slot="$form" :initialValues :resolver :validateOnValueUpdate="false" :validateOnBlur="true" :validateOnMount="['name']" @submit="onFormSubmit" class="flex flex-col gap-4 w-full sm:w-56">
|
||||
<div class="flex flex-col gap-2">
|
||||
<InputText name="username" type="text" placeholder="Username" fluid />
|
||||
<Message v-if="$form.username?.invalid" severity="error">{{ $form.username.error.message }}</Message>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<InputText name="name" type="text" placeholder="Name" fluid />
|
||||
<Message v-if="$form.name?.invalid" severity="error">{{ $form.name.error.message }}</Message>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<InputText name="surname" type="text" placeholder="Surname" fluid />
|
||||
<Message v-if="$form.surname?.invalid" severity="error">{{ $form.surname.error.message }}</Message>
|
||||
</div>
|
||||
<Button type="submit" severity="secondary" label="Submit" />
|
||||
</Form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@ -68,7 +80,9 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
initialValues: {
|
||||
username: ''
|
||||
username: '',
|
||||
name: '',
|
||||
surname: ''
|
||||
}
|
||||
};
|
||||
},
|
||||
|
@ -80,6 +94,14 @@ export default {
|
|||
errors.username = [{ message: 'Username is required.' }];
|
||||
}
|
||||
|
||||
if (!values.name) {
|
||||
errors.name = [{ message: 'Name is required.' }];
|
||||
}
|
||||
|
||||
if (!values.surname) {
|
||||
errors.surname = [{ message: 'Surname is required.' }];
|
||||
}
|
||||
|
||||
return {
|
||||
errors
|
||||
};
|
||||
|
@ -95,18 +117,64 @@ export default {
|
|||
`,
|
||||
composition: `
|
||||
<template>
|
||||
<Card>
|
||||
<template #title>Simple Card</template>
|
||||
<template #content>
|
||||
<p class="m-0">
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore sed consequuntur error repudiandae numquam deserunt quisquam repellat libero asperiores earum nam nobis, culpa ratione quam perferendis esse, cupiditate neque
|
||||
quas!
|
||||
</p>
|
||||
</template>
|
||||
</Card>
|
||||
<div class="card flex justify-center">
|
||||
<Toast />
|
||||
|
||||
<Form v-slot="$form" :initialValues :resolver :validateOnValueUpdate="false" :validateOnBlur="true" :validateOnMount="['name']" @submit="onFormSubmit" class="flex flex-col gap-4 w-full sm:w-56">
|
||||
<div class="flex flex-col gap-2">
|
||||
<InputText name="username" type="text" placeholder="Username" fluid />
|
||||
<Message v-if="$form.username?.invalid" severity="error">{{ $form.username.error.message }}</Message>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<InputText name="name" type="text" placeholder="Name" fluid />
|
||||
<Message v-if="$form.name?.invalid" severity="error">{{ $form.name.error.message }}</Message>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<InputText name="surname" type="text" placeholder="Surname" fluid />
|
||||
<Message v-if="$form.surname?.invalid" severity="error">{{ $form.surname.error.message }}</Message>
|
||||
</div>
|
||||
<Button type="submit" severity="secondary" label="Submit" />
|
||||
</Form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { useToast } from 'primevue/usetoast';
|
||||
|
||||
const toast = useToast();
|
||||
|
||||
const initialValues = ref({
|
||||
username: '',
|
||||
name: '',
|
||||
surname: ''
|
||||
});
|
||||
|
||||
const resolver = ({ values }) => {
|
||||
const errors = {};
|
||||
|
||||
if (!values.username) {
|
||||
errors.username = [{ message: 'Username is required.' }];
|
||||
}
|
||||
|
||||
if (!values.name) {
|
||||
errors.name = [{ message: 'Name is required.' }];
|
||||
}
|
||||
|
||||
if (!values.surname) {
|
||||
errors.surname = [{ message: 'Surname is required.' }];
|
||||
}
|
||||
|
||||
return {
|
||||
errors
|
||||
};
|
||||
};
|
||||
|
||||
const onFormSubmit = ({ valid }) => {
|
||||
if (valid) {
|
||||
toast.add({ severity: 'success', summary: 'Form is submitted.', life: 3000 });
|
||||
}
|
||||
}
|
||||
<\/script>
|
||||
`
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue