Dynamic Forms
Schema Validation
vue
<script lang="ts" setup>
import { useValibotSchema } from 'vue-formor';
import { nullish, object, string, minLength, custom } from 'valibot';
const schema = useValibotSchema(
object({
language: nullish(string([minLength(1, msgs.required)]), ''),
preprocessor: nullish(
string([custom((input) => state.valibotForm.language === 'js' && !!input, msgs.require)]),
),
}),
toRef(state, 'valibotForm'),
toRef(state, 'valibotValdn'),
);
</script>
vue
<script lang="ts" setup>
import { useZodSchema } from 'vue-formor';
import { z } from 'zod';
const schema = useZodSchema(
z.object({
language: z.string({ required_error: msgs.required }).nonempty(msgs.required),
preprocessor: z
.string()
.optional()
.refine((val) => {
if (state.zodForm.language === 'js' && !val) return false;
return true;
}, msgs.required),
}),
toRef(state, 'zodForm'),
toRef(state, 'zodValdn'),
);
</script>
vue
<script lang="ts" setup>
import { useYupSchema } from 'vue-formor';
import { object, string } from 'yup';
const schema = useYupSchema(
object({
language: string().required(msgs.required),
preprocessor: string()
.optional()
.test('letters', msgs.required, (value) => {
if (state.yupForm.language === 'js' && !value) return false;
return true;
}),
}),
toRef(state, 'yupForm'),
toRef(state, 'yupValdn'),
);
</script>
Final Code
vue
<script lang="ts" setup>
import { reactive, toRef } from 'vue';
import { useValibotSchema } from 'vue-formor';
import { nullish, object, string, minLength, custom } from 'valibot';
interface DynamicForms {
language: string;
preprocessor: string;
}
const state = reactive({
valibotForm: {} as DynamicForms,
valibotValdn: {} as Record<string, string>,
});
const msgs = {
required: `This is a required field`,
};
const schema = useValibotSchema(
object({
language: nullish(string([minLength(1, msgs.required)]), ''),
preprocessor: nullish(
string([custom((input) => state.valibotForm.language === 'js' && !!input, msgs.require)]),
),
}),
toRef(state, 'valibotForm'),
toRef(state, 'valibotValdn'),
);
const changeLanguage = () => {
state.valibotForm.preprocessor = '';
};
const submit = () => {
if (schema.validate()) {
// passed
}
};
</script>
<template>
<fieldset>
<legend>Dynamic Forms</legend>
<form>
<div class="flex gap-2">
<label for="language">Language:</label>
<select id="language" v-model="state.valibotForm.language" @change="changeLanguage">
<option value="">None</option>
<option value="html">HTML</option>
<option value="css">CSS</option>
<option value="js">JavaScript</option>
</select>
<div class="text-red-500">{{ state.valibotValdn.language }}</div>
</div>
<div class="flex gap-2">
<label for="preprocessor">Preprocessor:</label>
<select
id="preprocessor"
v-model="state.valibotForm.preprocessor"
:disabled="state.valibotForm.language !== 'js'"
>
<option value="">None</option>
<option value="ts">TypeScript</option>
</select>
<div class="text-red-500">{{ state.valibotValdn.preprocessor }}</div>
</div>
<button type="button" @click="submit">Submit</button>
</form>
<pre>{{ state.valibotForm }}</pre>
<pre>{{ state.valibotValdn }}</pre>
</fieldset>
</template>
<style scoped>
.flex {
display: flex;
}
.gap-2 {
gap: 0.5rem;
}
.text-red-500 {
--un-text-opacity: 1;
color: rgba(239, 68, 68, var(--un-text-opacity));
}
</style>
vue
<script lang="ts" setup>
import { reactive, toRef } from 'vue';
import { useZodSchema } from 'vue-formor';
import { z } from 'zod';
interface DynamicForms {
language: string;
preprocessor: string;
}
const state = reactive({
zodForm: {} as DynamicForms,
zodValdn: {} as Record<string, string>,
});
const msgs = {
required: `This is a required field`,
};
const schema = useZodSchema(
z.object({
language: z.string({ required_error: msgs.required }).nonempty(msgs.required),
preprocessor: z
.string()
.optional()
.refine((val) => {
if (state.zodForm.language === 'js' && !val) return false;
return true;
}, msgs.required),
}),
toRef(state, 'zodForm'),
toRef(state, 'zodValdn'),
);
const changeLanguage = () => {
state.zodForm.preprocessor = '';
};
const submit = () => {
if (schema.validate()) {
// passed
}
};
</script>
<template>
<fieldset>
<legend>Dynamic Forms</legend>
<form>
<div class="flex gap-2">
<label for="language">Language:</label>
<select id="language" v-model="state.zodForm.language" @change="changeLanguage">
<option value="">None</option>
<option value="html">HTML</option>
<option value="css">CSS</option>
<option value="js">JavaScript</option>
</select>
<div class="text-red-500">{{ state.zodValdn.language }}</div>
</div>
<div class="flex gap-2">
<label for="preprocessor">Preprocessor:</label>
<select
id="preprocessor"
v-model="state.zodForm.preprocessor"
:disabled="state.zodForm.language !== 'js'"
>
<option value="">None</option>
<option value="ts">TypeScript</option>
</select>
<div class="text-red-500">{{ state.zodValdn.preprocessor }}</div>
</div>
<button type="button" @click="submit">Submit</button>
</form>
<pre>{{ state.zodForm }}</pre>
<pre>{{ state.zodValdn }}</pre>
</fieldset>
</template>
<style scoped>
.flex {
display: flex;
}
.gap-2 {
gap: 0.5rem;
}
.text-red-500 {
--un-text-opacity: 1;
color: rgba(239, 68, 68, var(--un-text-opacity));
}
</style>
vue
<script lang="ts" setup>
import { reactive, toRef } from 'vue';
import { useYupSchema } from 'vue-formor';
import { object, string } from 'yup';
interface DynamicForms {
language: string;
preprocessor: string;
}
const state = reactive({
yupForm: {} as DynamicForms,
yupValdn: {} as Record<string, string>,
});
const msgs = {
required: `This is a required field`,
};
const schema = useYupSchema(
object({
language: string().required(msgs.required),
preprocessor: string()
.optional()
.test('letters', msgs.required, (value) => {
if (state.yupForm.language === 'js' && !value) return false;
return true;
}),
}),
toRef(state, 'yupForm'),
toRef(state, 'yupValdn'),
);
const changeLanguage = () => {
state.yupForm.preprocessor = '';
};
const submit = () => {
if (schema.validate()) {
// passed
}
};
</script>
<template>
<fieldset>
<legend>Dynamic Forms</legend>
<form>
<div class="flex gap-2">
<label for="language">Language:</label>
<select id="language" v-model="state.yupForm.language" @change="changeLanguage">
<option value="">None</option>
<option value="html">HTML</option>
<option value="css">CSS</option>
<option value="js">JavaScript</option>
</select>
<div class="text-red-500">{{ state.yupValdn.language }}</div>
</div>
<div class="flex gap-2">
<label for="preprocessor">Preprocessor:</label>
<select
id="preprocessor"
v-model="state.yupForm.preprocessor"
:disabled="state.yupForm.language !== 'js'"
>
<option value="">None</option>
<option value="ts">TypeScript</option>
</select>
<div class="text-red-500">{{ state.yupValdn.preprocessor }}</div>
</div>
<button type="button" @click="submit">Submit</button>
</form>
<pre>{{ state.yupForm }}</pre>
<pre>{{ state.yupValdn }}</pre>
</fieldset>
</template>
<style scoped>
.flex {
display: flex;
}
.gap-2 {
gap: 0.5rem;
}
.text-red-500 {
--un-text-opacity: 1;
color: rgba(239, 68, 68, var(--un-text-opacity));
}
</style>