primevue-mirror/apps/showcase/doc/forms/DynamicDoc.vue

362 lines
16 KiB
Vue
Raw Normal View History

2024-10-23 04:05:27 +00:00
<template>
<DocSectionText v-bind="$attrs">
2024-10-31 07:56:10 +00:00
<p>
This section demonstrates how to create a dynamic form using a custom Form component. It showcases an example where form fields are generated dynamically based on the provided configuration, allowing for flexible form structures. The
components named <i>Dynamic*</i> shown in this example are not built-in, and only available for sampling purposes. First form uses a declarative approach whereas second form goes for a programmatic approach. We suggest running this sample
in StackBlitz to view the comprehensive implementation.
</p>
2024-10-23 04:05:27 +00:00
</DocSectionText>
<div class="card grid md:grid-cols-2 gap-4 w-full">
<Fieldset legend="Form 1" pt:content:class="flex justify-center">
<DynamicForm @submit="onFormSubmit('Form 1', $event)">
<DynamicFormField groupId="userId_1" name="username">
<DynamicFormLabel>Username</DynamicFormLabel>
<DynamicFormControl defaultValue="PrimeVue" fluid :schema="userNameSchema" />
<DynamicFormMessage />
</DynamicFormField>
<DynamicFormField groupId="passId_1" name="password">
<DynamicFormLabel>Password</DynamicFormLabel>
2024-10-23 21:57:52 +00:00
<DynamicFormControl as="Password" :feedback="false" toggleMask fluid :schema="passwordSchema" />
2024-10-23 04:05:27 +00:00
<DynamicFormMessage errorType="minimum" />
<DynamicFormMessage errorType="maximum" />
<DynamicFormMessage errorType="uppercase" severity="warn" />
<DynamicFormMessage errorType="lowercase" severity="warn" />
<DynamicFormMessage errorType="number" severity="secondary" />
</DynamicFormField>
<DynamicFormSubmit />
</DynamicForm>
</Fieldset>
<Fieldset legend="Form 2" pt:content:class="flex justify-center">
<DynamicForm :fields @submit="onFormSubmit('Form 2', $event)" />
</Fieldset>
</div>
2024-10-23 11:06:59 +00:00
<DocSectionCode :code="code" :dependencies="{ zod: '3.23.8' }" />
2024-10-23 04:05:27 +00:00
</template>
<script>
import { markRaw } from 'vue';
import { z } from 'zod';
import DynamicForm from './dynamic/DynamicForm.vue';
import DynamicFormControl from './dynamic/DynamicFormControl.vue';
import DynamicFormField from './dynamic/DynamicFormField.vue';
import DynamicFormLabel from './dynamic/DynamicFormLabel.vue';
import DynamicFormMessage from './dynamic/DynamicFormMessage.vue';
import DynamicFormSubmit from './dynamic/DynamicFormSubmit.vue';
export default {
data() {
return {
2024-10-23 04:11:19 +00:00
userNameSchema: z.string().min(1, { message: 'Username is required.' }),
2024-10-23 04:05:27 +00:00
passwordSchema: z
.string()
.min(3, { message: 'Password must be at least 3 characters long.' })
.max(8, { message: 'Password must not exceed 8 characters.' })
.refine((value) => /[a-z]/.test(value), {
errorType: 'lowercase',
message: 'Password must contain at least one lowercase letter.'
})
.refine((value) => /[A-Z]/.test(value), {
errorType: 'uppercase',
message: 'Password must contain at least one uppercase letter.'
})
.refine((value) => /\d/.test(value), {
errorType: 'number',
message: 'Password must contain at least one number.'
}),
fields: {
username: {
groupId: 'userId_2',
label: 'Username',
defaultValue: 'PrimeVue',
fluid: true,
2024-10-23 04:11:19 +00:00
schema: z.string().min(1, { message: 'Username is required.' })
2024-10-23 04:05:27 +00:00
},
password: {
groupId: 'passId_2',
label: 'Password',
as: 'Password',
feedback: false,
2024-10-23 21:57:52 +00:00
toggleMask: true,
2024-10-23 04:05:27 +00:00
fluid: true,
messages: [{ errorType: 'minimum' }, { errorType: 'maximum' }, { errorType: 'uppercase', severity: 'warn' }, { errorType: 'lowercase', severity: 'warn' }, { errorType: 'number', severity: 'secondary' }],
schema: z
.string()
.min(3, { message: 'Password must be at least 3 characters long.' })
.max(8, { message: 'Password must not exceed 8 characters.' })
.refine((value) => /[a-z]/.test(value), {
errorType: 'lowercase',
message: 'Password must contain at least one lowercase letter.'
})
.refine((value) => /[A-Z]/.test(value), {
errorType: 'uppercase',
message: 'Password must contain at least one uppercase letter.'
})
.refine((value) => /\d/.test(value), {
errorType: 'number',
message: 'Password must contain at least one number.'
})
}
},
code: {
basic: `
<Fieldset legend="Form 1" pt:content:class="flex justify-center">
<DynamicForm @submit="onFormSubmit('Form 1', $event)">
<DynamicFormField groupId="userId_1" name="username">
<DynamicFormLabel>Username</DynamicFormLabel>
<DynamicFormControl defaultValue="PrimeVue" fluid :schema="userNameSchema" />
<DynamicFormMessage />
</DynamicFormField>
<DynamicFormField groupId="passId_1" name="password">
<DynamicFormLabel>Password</DynamicFormLabel>
2024-10-23 21:57:52 +00:00
<DynamicFormControl as="Password" :feedback="false" toggleMask fluid :schema="passwordSchema" />
2024-10-23 04:05:27 +00:00
<DynamicFormMessage errorType="minimum" />
<DynamicFormMessage errorType="maximum" />
<DynamicFormMessage errorType="uppercase" severity="warn" />
<DynamicFormMessage errorType="lowercase" severity="warn" />
<DynamicFormMessage errorType="number" severity="secondary" />
</DynamicFormField>
<DynamicFormSubmit />
</DynamicForm>
</Fieldset>
<Fieldset legend="Form 2" pt:content:class="flex justify-center">
<DynamicForm :fields @submit="onFormSubmit('Form 2', $event)" />
</Fieldset>
`,
options: `
<template>
2024-10-23 11:06:59 +00:00
<div class="card grid md:grid-cols-2 gap-4 w-full">
<Toast />
<Fieldset legend="Form 1" pt:content:class="flex justify-center">
<DynamicForm @submit="onFormSubmit('Form 1', $event)">
<DynamicFormField groupId="userId_1" name="username">
<DynamicFormLabel>Username</DynamicFormLabel>
<DynamicFormControl defaultValue="PrimeVue" fluid :schema="userNameSchema" />
<DynamicFormMessage />
</DynamicFormField>
<DynamicFormField groupId="passId_1" name="password">
<DynamicFormLabel>Password</DynamicFormLabel>
2024-10-23 21:57:52 +00:00
<DynamicFormControl as="Password" :feedback="false" toggleMask fluid :schema="passwordSchema" />
2024-10-23 11:06:59 +00:00
<DynamicFormMessage errorType="minimum" />
<DynamicFormMessage errorType="maximum" />
<DynamicFormMessage errorType="uppercase" severity="warn" />
<DynamicFormMessage errorType="lowercase" severity="warn" />
<DynamicFormMessage errorType="number" severity="secondary" />
</DynamicFormField>
<DynamicFormSubmit />
</DynamicForm>
</Fieldset>
2024-10-23 04:05:27 +00:00
2024-10-23 11:06:59 +00:00
<Fieldset legend="Form 2" pt:content:class="flex justify-center">
<DynamicForm :fields @submit="onFormSubmit('Form 2', $event)" />
</Fieldset>
</div>
2024-10-23 04:05:27 +00:00
</template>
<script>
import { markRaw } from 'vue';
import { z } from 'zod';
import DynamicForm from './dynamic/DynamicForm.vue';
import DynamicFormControl from './dynamic/DynamicFormControl.vue';
import DynamicFormField from './dynamic/DynamicFormField.vue';
import DynamicFormLabel from './dynamic/DynamicFormLabel.vue';
import DynamicFormMessage from './dynamic/DynamicFormMessage.vue';
import DynamicFormSubmit from './dynamic/DynamicFormSubmit.vue';
export default {
data() {
return {
2024-10-23 04:11:19 +00:00
userNameSchema: z.string().min(1, { message: 'Username is required.' }),
2024-10-23 04:05:27 +00:00
passwordSchema: z
.string()
.min(3, { message: 'Password must be at least 3 characters long.' })
.max(8, { message: 'Password must not exceed 8 characters.' })
.refine((value) => /[a-z]/.test(value), {
errorType: 'lowercase',
message: 'Password must contain at least one lowercase letter.'
})
.refine((value) => /[A-Z]/.test(value), {
errorType: 'uppercase',
message: 'Password must contain at least one uppercase letter.'
})
.refine((value) => /\d/.test(value), {
errorType: 'number',
message: 'Password must contain at least one number.'
}),
fields: {
username: {
groupId: 'userId_2',
label: 'Username',
defaultValue: 'PrimeVue',
fluid: true,
2024-10-23 04:11:19 +00:00
schema: z.string().min(1, { message: 'Username is required.' })
2024-10-23 04:05:27 +00:00
},
password: {
groupId: 'passId_2',
label: 'Password',
as: 'Password',
feedback: false,
2024-10-23 21:57:52 +00:00
toggleMask: true,
2024-10-23 04:05:27 +00:00
fluid: true,
messages: [{ errorType: 'minimum' }, { errorType: 'maximum' }, { errorType: 'uppercase', severity: 'warn' }, { errorType: 'lowercase', severity: 'warn' }, { errorType: 'number', severity: 'secondary' }],
schema: z
.string()
.min(3, { message: 'Password must be at least 3 characters long.' })
.max(8, { message: 'Password must not exceed 8 characters.' })
.refine((value) => /[a-z]/.test(value), {
errorType: 'lowercase',
message: 'Password must contain at least one lowercase letter.'
})
.refine((value) => /[A-Z]/.test(value), {
errorType: 'uppercase',
message: 'Password must contain at least one uppercase letter.'
})
.refine((value) => /\d/.test(value), {
errorType: 'number',
message: 'Password must contain at least one number.'
})
}
}
};
},
methods: {
onFormSubmit(text, { valid }) {
if (valid) {
this.$toast.add({ severity: 'success', summary: \`\${text} is submitted.\`, life: 3000 });
}
}
},
components: {
DynamicForm: markRaw(DynamicForm),
DynamicFormControl: markRaw(DynamicFormControl),
DynamicFormField: markRaw(DynamicFormField),
DynamicFormLabel: markRaw(DynamicFormLabel),
DynamicFormMessage: markRaw(DynamicFormMessage),
DynamicFormSubmit: markRaw(DynamicFormSubmit)
}
};
<\/script>
`,
composition: `
<template>
2024-10-23 11:06:59 +00:00
<div class="card grid md:grid-cols-2 gap-4 w-full">
<Toast />
<Fieldset legend="Form 1" pt:content:class="flex justify-center">
<DynamicForm @submit="onFormSubmit('Form 1', $event)">
<DynamicFormField groupId="userId_1" name="username">
<DynamicFormLabel>Username</DynamicFormLabel>
<DynamicFormControl defaultValue="PrimeVue" fluid :schema="userNameSchema" />
<DynamicFormMessage />
</DynamicFormField>
<DynamicFormField groupId="passId_1" name="password">
<DynamicFormLabel>Password</DynamicFormLabel>
2024-10-23 21:57:52 +00:00
<DynamicFormControl as="Password" :feedback="false" toggleMask fluid :schema="passwordSchema" />
2024-10-23 11:06:59 +00:00
<DynamicFormMessage errorType="minimum" />
<DynamicFormMessage errorType="maximum" />
<DynamicFormMessage errorType="uppercase" severity="warn" />
<DynamicFormMessage errorType="lowercase" severity="warn" />
<DynamicFormMessage errorType="number" severity="secondary" />
</DynamicFormField>
<DynamicFormSubmit />
</DynamicForm>
</Fieldset>
<Fieldset legend="Form 2" pt:content:class="flex justify-center">
<DynamicForm :fields @submit="onFormSubmit('Form 2', $event)" />
</Fieldset>
</div>
2024-10-23 04:05:27 +00:00
</template>
<script setup>
2024-10-23 11:06:59 +00:00
import { reactive } from 'vue';
import { z } from 'zod';
import { useToast } from 'primevue/usetoast';
import DynamicForm from './dynamic/DynamicForm.vue';
import DynamicFormControl from './dynamic/DynamicFormControl.vue';
import DynamicFormField from './dynamic/DynamicFormField.vue';
import DynamicFormLabel from './dynamic/DynamicFormLabel.vue';
import DynamicFormMessage from './dynamic/DynamicFormMessage.vue';
import DynamicFormSubmit from './dynamic/DynamicFormSubmit.vue';
const toast = useToast();
const userNameSchema = z.string().min(1, { message: 'Username is required.' });
const passwordSchema = z
.string()
.min(3, { message: 'Password must be at least 3 characters long.' })
.max(8, { message: 'Password must not exceed 8 characters.' })
.refine((value) => /[a-z]/.test(value), {
errorType: 'lowercase',
message: 'Password must contain at least one lowercase letter.'
})
.refine((value) => /[A-Z]/.test(value), {
errorType: 'uppercase',
message: 'Password must contain at least one uppercase letter.'
})
.refine((value) => /\d/.test(value), {
errorType: 'number',
message: 'Password must contain at least one number.'
});
const fields = reactive({
username: {
groupId: 'userId_2',
label: 'Username',
defaultValue: 'PrimeVue',
fluid: true,
schema: userNameSchema
},
password: {
groupId: 'passId_2',
label: 'Password',
as: 'Password',
feedback: false,
2024-10-23 21:57:52 +00:00
toggleMask: true,
2024-10-23 11:06:59 +00:00
fluid: true,
messages: [
{ errorType: 'minimum' },
{ errorType: 'maximum' },
{ errorType: 'uppercase', severity: 'warn' },
{ errorType: 'lowercase', severity: 'warn' },
{ errorType: 'number', severity: 'secondary' }
],
schema: passwordSchema
}
});
const onFormSubmit = (text, { valid }) => {
if (valid) {
toast.add({
severity: 'success',
summary: \`\${text} is submitted.\`,
life: 3000
});
}
};
2024-10-23 04:05:27 +00:00
<\/script>
`
}
};
},
methods: {
onFormSubmit(text, { valid }) {
if (valid) {
this.$toast.add({ severity: 'success', summary: `${text} is submitted.`, life: 3000 });
}
}
},
components: {
DynamicForm: markRaw(DynamicForm),
DynamicFormControl: markRaw(DynamicFormControl),
DynamicFormField: markRaw(DynamicFormField),
DynamicFormLabel: markRaw(DynamicFormLabel),
DynamicFormMessage: markRaw(DynamicFormMessage),
DynamicFormSubmit: markRaw(DynamicFormSubmit)
}
};
</script>