Convert to composition API

pull/6632/head
Mert Sincan 2024-10-23 22:57:52 +01:00
parent eaa03d8e72
commit d2b191ed6e
8 changed files with 109 additions and 172 deletions

View File

@ -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' },

View File

@ -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>

View File

@ -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: {
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 props = defineProps({
fields: Object
});
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>

View File

@ -2,42 +2,27 @@
<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: {
as: {
type: String,
default: 'InputText'
},
schema: null,
defaultValue: {
default: ''
}
const props = defineProps({
as: {
type: String,
default: 'InputText'
},
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;
}
schema: null,
defaultValue: {
default: ''
}
};
});
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>

View File

@ -4,23 +4,22 @@
</div>
</template>
<script>
export default {
name: 'DynamicFormField',
props: {
groupId: {
type: String,
default: undefined
},
name: {
type: String,
default: undefined
}
<script setup>
import { provide } from 'vue';
const props = defineProps({
groupId: {
type: String,
default: undefined
},
provide() {
return {
$fcDynamicFormField: this
};
name: {
type: String,
default: undefined
}
};
});
provide('$fcDynamicFormField', {
groupId: props.groupId,
name: props.name
});
</script>

View File

@ -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>

View File

@ -4,51 +4,29 @@
</Message>
</template>
<script>
<script setup>
import { isNotEmpty } from '@primeuix/utils';
import { computed, inject } from 'vue';
export default {
name: 'DynamicFormLabel',
props: {
errorType: {
type: String,
default: undefined
},
severity: {
type: String,
default: 'error'
}
const props = defineProps({
errorType: {
type: String,
default: undefined
},
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;
}
severity: {
type: String,
default: 'error'
}
};
});
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>

View File

@ -2,18 +2,17 @@
<Button type="submit" :severity :label />
</template>
<script>
export default {
name: 'DynamicFormSubmit',
props: {
severity: {
type: String,
default: 'secondary'
},
label: {
type: String,
default: 'Submit'
}
<script setup>
import Button from 'primevue/button';
const props = defineProps({
severity: {
type: String,
default: 'secondary'
},
label: {
type: String,
default: 'Submit'
}
};
});
</script>