Convert to composition API
parent
eaa03d8e72
commit
d2b191ed6e
|
@ -12,7 +12,7 @@
|
|||
</DynamicFormField>
|
||||
<DynamicFormField groupId="passId_1" name="password">
|
||||
<DynamicFormLabel>Password</DynamicFormLabel>
|
||||
<DynamicFormControl as="Password" :feedback="false" fluid :schema="passwordSchema" />
|
||||
<DynamicFormControl as="Password" :feedback="false" toggleMask fluid :schema="passwordSchema" />
|
||||
<DynamicFormMessage errorType="minimum" />
|
||||
<DynamicFormMessage errorType="maximum" />
|
||||
<DynamicFormMessage errorType="uppercase" severity="warn" />
|
||||
|
@ -73,6 +73,7 @@ export default {
|
|||
label: 'Password',
|
||||
as: 'Password',
|
||||
feedback: false,
|
||||
toggleMask: true,
|
||||
fluid: true,
|
||||
messages: [{ errorType: 'minimum' }, { errorType: 'maximum' }, { errorType: 'uppercase', severity: 'warn' }, { errorType: 'lowercase', severity: 'warn' }, { errorType: 'number', severity: 'secondary' }],
|
||||
schema: z
|
||||
|
@ -104,7 +105,7 @@ export default {
|
|||
</DynamicFormField>
|
||||
<DynamicFormField groupId="passId_1" name="password">
|
||||
<DynamicFormLabel>Password</DynamicFormLabel>
|
||||
<DynamicFormControl as="Password" :feedback="false" fluid :schema="passwordSchema" />
|
||||
<DynamicFormControl as="Password" :feedback="false" toggleMask fluid :schema="passwordSchema" />
|
||||
<DynamicFormMessage errorType="minimum" />
|
||||
<DynamicFormMessage errorType="maximum" />
|
||||
<DynamicFormMessage errorType="uppercase" severity="warn" />
|
||||
|
@ -133,7 +134,7 @@ export default {
|
|||
</DynamicFormField>
|
||||
<DynamicFormField groupId="passId_1" name="password">
|
||||
<DynamicFormLabel>Password</DynamicFormLabel>
|
||||
<DynamicFormControl as="Password" :feedback="false" fluid :schema="passwordSchema" />
|
||||
<DynamicFormControl as="Password" :feedback="false" toggleMask fluid :schema="passwordSchema" />
|
||||
<DynamicFormMessage errorType="minimum" />
|
||||
<DynamicFormMessage errorType="maximum" />
|
||||
<DynamicFormMessage errorType="uppercase" severity="warn" />
|
||||
|
@ -193,6 +194,7 @@ export default {
|
|||
label: 'Password',
|
||||
as: 'Password',
|
||||
feedback: false,
|
||||
toggleMask: true,
|
||||
fluid: true,
|
||||
messages: [{ errorType: 'minimum' }, { errorType: 'maximum' }, { errorType: 'uppercase', severity: 'warn' }, { errorType: 'lowercase', severity: 'warn' }, { errorType: 'number', severity: 'secondary' }],
|
||||
schema: z
|
||||
|
@ -247,7 +249,7 @@ export default {
|
|||
</DynamicFormField>
|
||||
<DynamicFormField groupId="passId_1" name="password">
|
||||
<DynamicFormLabel>Password</DynamicFormLabel>
|
||||
<DynamicFormControl as="Password" :feedback="false" fluid :schema="passwordSchema" />
|
||||
<DynamicFormControl as="Password" :feedback="false" toggleMask fluid :schema="passwordSchema" />
|
||||
<DynamicFormMessage errorType="minimum" />
|
||||
<DynamicFormMessage errorType="maximum" />
|
||||
<DynamicFormMessage errorType="uppercase" severity="warn" />
|
||||
|
@ -309,6 +311,7 @@ const fields = reactive({
|
|||
label: 'Password',
|
||||
as: 'Password',
|
||||
feedback: false,
|
||||
toggleMask: true,
|
||||
fluid: true,
|
||||
messages: [
|
||||
{ errorType: 'minimum' },
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
<p>The <i>submit</i> callback provides an object containing the form's validity, all errors, and current states. This offers access to the form values as well as validation status and any existing errors during submission.</p>
|
||||
</DocSectionText>
|
||||
<div class="card flex justify-center">
|
||||
<Form v-slot="$form" :initialValues :resolver @submit="onFormSubmit" class="flex flex-col gap-4 w-full sm:w-56">
|
||||
<Form v-slot="$form" :initialValues :resolver @submit="onFormSubmit" class="flex flex-col gap-4 w-full sm:w-60">
|
||||
<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 />
|
||||
<Password name="password" placeholder="Password" :feedback="false" toggleMask 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>
|
||||
|
@ -53,13 +53,13 @@ export default {
|
|||
),
|
||||
code: {
|
||||
basic: `
|
||||
<Form v-slot="$form" :initialValues :resolver @submit="onFormSubmit" class="flex flex-col gap-4 w-full sm:w-56">
|
||||
<Form v-slot="$form" :initialValues :resolver @submit="onFormSubmit" class="flex flex-col gap-4 w-full sm:w-60">
|
||||
<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 />
|
||||
<Password name="password" placeholder="Password" :feedback="false" toggleMask 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>
|
||||
|
@ -74,13 +74,13 @@ export default {
|
|||
<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">
|
||||
<Form v-slot="$form" :initialValues :resolver @submit="onFormSubmit" class="flex flex-col gap-4 w-full sm:w-60">
|
||||
<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 />
|
||||
<Password name="password" placeholder="Password" :feedback="false" toggleMask 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>
|
||||
|
@ -145,13 +145,13 @@ export default {
|
|||
<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">
|
||||
<Form v-slot="$form" :initialValues :resolver @submit="onFormSubmit" class="flex flex-col gap-4 w-full sm:w-60">
|
||||
<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 />
|
||||
<Password name="password" placeholder="Password" :feedback="false" toggleMask 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>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</Form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { isNotEmpty } from '@primeuix/utils';
|
||||
import { zodResolver } from '@primevue/form/resolvers';
|
||||
import { z } from 'zod';
|
||||
|
@ -23,43 +23,24 @@ import DynamicFormLabel from './DynamicFormLabel.vue';
|
|||
import DynamicFormMessage from './DynamicFormMessage.vue';
|
||||
import DynamicFormSubmit from './DynamicFormSubmit.vue';
|
||||
|
||||
export default {
|
||||
name: 'DynamicForm',
|
||||
emits: ['submit'],
|
||||
props: {
|
||||
const props = defineProps({
|
||||
fields: Object
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
$fcDynamicForm: this
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
defaultValues: {},
|
||||
schemas: {}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
addField(name, schema, defaultValue) {
|
||||
schema && (this.schemas[name] = schema);
|
||||
this.defaultValues[name] = defaultValue;
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
resolver() {
|
||||
return isNotEmpty(this.schemas) ? zodResolver(z.object(this.schemas)) : undefined;
|
||||
},
|
||||
initialValues() {
|
||||
return this.defaultValues;
|
||||
}
|
||||
},
|
||||
components: {
|
||||
DynamicFormControl,
|
||||
DynamicFormField,
|
||||
DynamicFormLabel,
|
||||
DynamicFormMessage,
|
||||
DynamicFormSubmit
|
||||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits(['submit']);
|
||||
|
||||
const defaultValues = ref({});
|
||||
const schemas = ref({});
|
||||
|
||||
const resolver = computed(() => (isNotEmpty(schemas.value) ? zodResolver(z.object(schemas.value)) : undefined));
|
||||
const initialValues = computed(() => defaultValues.value);
|
||||
|
||||
const addField = (name, schema, defaultValue) => {
|
||||
schema && (schemas.value[name] = schema);
|
||||
defaultValues.value[name] = defaultValue;
|
||||
};
|
||||
|
||||
provide('$fcDynamicForm', {
|
||||
addField
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -2,12 +2,11 @@
|
|||
<component :is="component" :id :name class="w-full" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import * as PrimeVue from 'primevue/primevue';
|
||||
import { computed, inject } from 'vue';
|
||||
|
||||
export default {
|
||||
name: 'DynamicFormControl',
|
||||
props: {
|
||||
const props = defineProps({
|
||||
as: {
|
||||
type: String,
|
||||
default: 'InputText'
|
||||
|
@ -16,28 +15,14 @@ export default {
|
|||
defaultValue: {
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
inject: {
|
||||
$fcDynamicForm: {
|
||||
default: undefined
|
||||
},
|
||||
$fcDynamicFormField: {
|
||||
default: undefined
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$fcDynamicForm?.addField(this.name, this.schema, this.defaultValue);
|
||||
},
|
||||
computed: {
|
||||
id() {
|
||||
return this.$fcDynamicFormField?.$props.groupId;
|
||||
},
|
||||
name() {
|
||||
return this.$fcDynamicFormField?.$props.name;
|
||||
},
|
||||
component() {
|
||||
return PrimeVue[this.as] ?? this.as;
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
const $fcDynamicForm = inject('$fcDynamicForm', undefined);
|
||||
const $fcDynamicFormField = inject('$fcDynamicFormField', undefined);
|
||||
|
||||
const id = computed(() => $fcDynamicFormField?.groupId);
|
||||
const name = computed(() => $fcDynamicFormField?.name);
|
||||
const component = computed(() => PrimeVue[props.as] ?? props.as);
|
||||
|
||||
$fcDynamicForm?.addField(name.value, props.schema, props.defaultValue);
|
||||
</script>
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'DynamicFormField',
|
||||
props: {
|
||||
<script setup>
|
||||
import { provide } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
groupId: {
|
||||
type: String,
|
||||
default: undefined
|
||||
|
@ -16,11 +16,10 @@ export default {
|
|||
type: String,
|
||||
default: undefined
|
||||
}
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
$fcDynamicFormField: this
|
||||
};
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
provide('$fcDynamicFormField', {
|
||||
groupId: props.groupId,
|
||||
name: props.name
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -4,18 +4,10 @@
|
|||
</label>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'DynamicFormLabel',
|
||||
inject: {
|
||||
$fcDynamicFormField: {
|
||||
default: undefined
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
htmlFor() {
|
||||
return this.$fcDynamicFormField?.$props.groupId;
|
||||
}
|
||||
}
|
||||
};
|
||||
<script setup>
|
||||
import { computed, inject } from 'vue';
|
||||
|
||||
const $fcDynamicFormField = inject('$fcDynamicFormField', undefined);
|
||||
|
||||
const htmlFor = computed(() => $fcDynamicFormField?.groupId);
|
||||
</script>
|
||||
|
|
|
@ -4,12 +4,11 @@
|
|||
</Message>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { isNotEmpty } from '@primeuix/utils';
|
||||
import { computed, inject } from 'vue';
|
||||
|
||||
export default {
|
||||
name: 'DynamicFormLabel',
|
||||
props: {
|
||||
const props = defineProps({
|
||||
errorType: {
|
||||
type: String,
|
||||
default: undefined
|
||||
|
@ -18,37 +17,16 @@ export default {
|
|||
type: String,
|
||||
default: 'error'
|
||||
}
|
||||
},
|
||||
inject: {
|
||||
$pcForm: {
|
||||
default: undefined
|
||||
},
|
||||
$fcDynamicFormField: {
|
||||
default: undefined
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
visible() {
|
||||
return this.invalid && (this.error || this.errorType === undefined);
|
||||
},
|
||||
message() {
|
||||
return this.errorType ? this.error?.message : this.errors?.[0]?.message;
|
||||
},
|
||||
error() {
|
||||
return this.errors?.find((error) => error.errorType === this.errorType || isNotEmpty(error[this.errorType]));
|
||||
},
|
||||
fieldName() {
|
||||
return this.$fcDynamicFormField?.$props.name;
|
||||
},
|
||||
state() {
|
||||
return this.$pcForm?.states?.[this.fieldName];
|
||||
},
|
||||
errors() {
|
||||
return this.state?.errors;
|
||||
},
|
||||
invalid() {
|
||||
return this.state?.invalid;
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
const $pcForm = inject('$pcForm', undefined); // Inject PrimeVue Form component
|
||||
const $fcDynamicFormField = inject('$fcDynamicFormField', undefined);
|
||||
|
||||
const fieldName = computed(() => $fcDynamicFormField?.name);
|
||||
const state = computed(() => $pcForm?.states?.[fieldName.value]);
|
||||
const errors = computed(() => state.value?.errors);
|
||||
const invalid = computed(() => state.value?.invalid);
|
||||
const error = computed(() => errors.value?.find((error) => props.errorType === error.errorType || isNotEmpty(error[props.errorType])));
|
||||
const message = computed(() => (props.errorType ? error.value?.message : errors.value?.[0]?.message));
|
||||
const visible = computed(() => invalid.value && (error.value || props.errorType === undefined));
|
||||
</script>
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
<Button type="submit" :severity :label />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'DynamicFormSubmit',
|
||||
props: {
|
||||
<script setup>
|
||||
import Button from 'primevue/button';
|
||||
|
||||
const props = defineProps({
|
||||
severity: {
|
||||
type: String,
|
||||
default: 'secondary'
|
||||
|
@ -14,6 +14,5 @@ export default {
|
|||
type: String,
|
||||
default: 'Submit'
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
|
Loading…
Reference in New Issue