Refactor on forms package
parent
0432047fd4
commit
83225d56bc
|
@ -53,7 +53,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@primeuix/utils": "catalog:",
|
"@primeuix/utils": "catalog:",
|
||||||
"@primeuix/form": "catalog:",
|
"@primeuix/forms": "catalog:",
|
||||||
"@primevue/core": "workspace:*"
|
"@primevue/core": "workspace:*"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|
|
@ -251,9 +251,9 @@ export interface FormSlots {
|
||||||
export interface FormEmitsOptions {
|
export interface FormEmitsOptions {
|
||||||
/**
|
/**
|
||||||
* Emitted when the form is submitted.
|
* Emitted when the form is submitted.
|
||||||
* @param {Event} event - Original DOM event.
|
* @param {FormSubmitEvent} event - Custom submit event.
|
||||||
*/
|
*/
|
||||||
submit: (event: Event) => void;
|
submit: (event: FormSubmitEvent) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export declare type FormEmits = EmitFn<FormEmitsOptions>;
|
export declare type FormEmits = EmitFn<FormEmitsOptions>;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import BaseComponent from '@primevue/core/basecomponent';
|
import BaseComponent from '@primevue/core/basecomponent';
|
||||||
import FormFieldStyle from '@primevue/forms/field/style';
|
import FormFieldStyle from '@primevue/forms/formfield/style';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'BaseFormField',
|
name: 'BaseFormField',
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* FormField is a helper component that provides validation and tracking for form fields.
|
* FormField is a helper component that provides validation and tracking for form fields.
|
||||||
* It is a helper component for the Form component.
|
|
||||||
*
|
*
|
||||||
* [Live Demo](https://www.primevue.org/form/)
|
* [Live Demo](https://www.primevue.org/form/)
|
||||||
*
|
*
|
||||||
* @module formfield
|
* @module formfield
|
||||||
* @todo Add more documentation
|
|
||||||
*/
|
*/
|
||||||
import type { DefineComponent, DesignToken, EmitFn, PassThrough } from '@primevue/core';
|
import type { DefineComponent, DesignToken, EmitFn, PassThrough } from '@primevue/core';
|
||||||
import type { ComponentHooks } from '@primevue/core/basecomponent';
|
import type { ComponentHooks } from '@primevue/core/basecomponent';
|
||||||
import { VNode } from 'vue';
|
import { Component, VNode } from 'vue';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* From primevue/passthrough/index.d.ts
|
* From primevue/passthrough/index.d.ts
|
||||||
|
@ -78,49 +76,88 @@ export interface FormFieldPassThroughAttributes {
|
||||||
*/
|
*/
|
||||||
export interface FormFieldResolverOptions {
|
export interface FormFieldResolverOptions {
|
||||||
/**
|
/**
|
||||||
* The values of the form fields.
|
* The value of the form field.
|
||||||
*/
|
*/
|
||||||
values: Record<string, any>;
|
value: any;
|
||||||
/**
|
/**
|
||||||
* The names of the form fields.
|
* The name of the form field.
|
||||||
*/
|
*/
|
||||||
names: string[] | undefined;
|
name: string | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Submit events
|
* Defines valid properties in Form component.
|
||||||
*/
|
*/
|
||||||
export interface FormFieldSubmitEvent {
|
export interface FormFieldProps {
|
||||||
/**
|
/**
|
||||||
* The original DOM event.
|
* A function that resolves validation logic.
|
||||||
|
* @param {FormResolverOptions} e - Resolver options
|
||||||
*/
|
*/
|
||||||
originalEvent: Event;
|
resolver?: (e: FormFieldResolverOptions) => any | undefined;
|
||||||
/**
|
/**
|
||||||
* The form values.
|
* The initial value for the form field.
|
||||||
*/
|
*/
|
||||||
values: Record<string, any>;
|
initialValue?: any;
|
||||||
/**
|
/**
|
||||||
* The form state.
|
* Whether to validate the form field when the value change.
|
||||||
*/
|
*/
|
||||||
states: Record<string, FormFieldState>;
|
validateOnValueUpdate?: boolean | undefined;
|
||||||
/**
|
/**
|
||||||
* Whether the form is valid.
|
* Whether to validate the form field when it loses focus (on blur).
|
||||||
*/
|
*/
|
||||||
valid: boolean;
|
validateOnBlur?: boolean | undefined;
|
||||||
/**
|
/**
|
||||||
* The form errors.
|
* Whether to validate the form field immediately after the form is mounted.
|
||||||
*/
|
*/
|
||||||
errors: any[];
|
validateOnMount?: boolean | undefined;
|
||||||
/**
|
/**
|
||||||
* Resets the form.
|
* Whether to validate the form field when the form is submitted.
|
||||||
*/
|
*/
|
||||||
reset: () => void;
|
validateOnSubmit?: boolean | undefined;
|
||||||
|
/**
|
||||||
|
* Use to change the HTML tag of root element.
|
||||||
|
* @defaultValue DIV
|
||||||
|
*/
|
||||||
|
as?: string | Component | undefined;
|
||||||
|
/**
|
||||||
|
* When enabled, it changes the default rendered element for the one passed as a child element.
|
||||||
|
* @defaultValue false
|
||||||
|
*/
|
||||||
|
asChild?: boolean | undefined;
|
||||||
|
/**
|
||||||
|
* It generates scoped CSS variables using design tokens for the component.
|
||||||
|
*/
|
||||||
|
dt?: DesignToken<any>;
|
||||||
|
/**
|
||||||
|
* Used to pass attributes to DOM elements inside the component.
|
||||||
|
* @type {FormPassThroughOptions}
|
||||||
|
*/
|
||||||
|
pt?: PassThrough<FormFieldPassThroughOptions>;
|
||||||
|
/**
|
||||||
|
* Used to configure passthrough(pt) options of the component.
|
||||||
|
* @type {PassThroughOptions}
|
||||||
|
*/
|
||||||
|
ptOptions?: PassThroughOptions;
|
||||||
|
/**
|
||||||
|
* When enabled, it removes component related styles in the core.
|
||||||
|
* @defaultValue false
|
||||||
|
*/
|
||||||
|
unstyled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The state of a form field.
|
* Defines valid slots in Form component.
|
||||||
*/
|
*/
|
||||||
export interface FormFieldState {
|
export interface FormFieldSlots {
|
||||||
|
/**
|
||||||
|
* Default content slot.
|
||||||
|
* @param {Object} scope - default slot's params.
|
||||||
|
*/
|
||||||
|
default: (scope: {
|
||||||
|
/**
|
||||||
|
* @todo
|
||||||
|
*/
|
||||||
|
props: any;
|
||||||
/**
|
/**
|
||||||
* The value of the form field.
|
* The value of the form field.
|
||||||
*/
|
*/
|
||||||
|
@ -159,110 +196,20 @@ export interface FormFieldState {
|
||||||
* @defaultValue []
|
* @defaultValue []
|
||||||
*/
|
*/
|
||||||
errors: any[];
|
errors: any[];
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines valid properties in Form component.
|
|
||||||
*/
|
|
||||||
export interface FormFieldProps {
|
|
||||||
/**
|
|
||||||
* A function that resolves validation logic.
|
|
||||||
* @param {FormResolverOptions} e - Resolver options
|
|
||||||
*/
|
|
||||||
resolver?: (e: FormFieldResolverOptions) => Promise<Record<string, any>> | Record<string, any> | undefined;
|
|
||||||
/**
|
|
||||||
* The initial values for the form fields.
|
|
||||||
*/
|
|
||||||
initialValues?: Record<string, any> | undefined;
|
|
||||||
/**
|
|
||||||
* Whether to validate the form fields when the values change.
|
|
||||||
* @defaultValue true
|
|
||||||
*/
|
|
||||||
validateOnValueUpdate?: boolean | string[] | undefined;
|
|
||||||
/**
|
|
||||||
* Whether to validate the form fields when they lose focus (on blur).
|
|
||||||
* @defaultValue false
|
|
||||||
*/
|
|
||||||
validateOnBlur?: boolean | string[] | undefined;
|
|
||||||
/**
|
|
||||||
* Whether to validate the form fields immediately after the form is mounted.
|
|
||||||
* @defaultValue false
|
|
||||||
*/
|
|
||||||
validateOnMount?: boolean | string[] | undefined;
|
|
||||||
/**
|
|
||||||
* Whether to validate the form fields when the form is submitted.
|
|
||||||
* @defaultValue true
|
|
||||||
*/
|
|
||||||
validateOnSubmit?: boolean | string[] | undefined;
|
|
||||||
/**
|
|
||||||
* It generates scoped CSS variables using design tokens for the component.
|
|
||||||
*/
|
|
||||||
dt?: DesignToken<any>;
|
|
||||||
/**
|
|
||||||
* Used to pass attributes to DOM elements inside the component.
|
|
||||||
* @type {FormPassThroughOptions}
|
|
||||||
*/
|
|
||||||
pt?: PassThrough<FormFieldPassThroughOptions>;
|
|
||||||
/**
|
|
||||||
* Used to configure passthrough(pt) options of the component.
|
|
||||||
* @type {PassThroughOptions}
|
|
||||||
*/
|
|
||||||
ptOptions?: PassThroughOptions;
|
|
||||||
/**
|
|
||||||
* When enabled, it removes component related styles in the core.
|
|
||||||
* @defaultValue false
|
|
||||||
*/
|
|
||||||
unstyled?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines valid slots in Form component.
|
|
||||||
*/
|
|
||||||
export interface FormSlots {
|
|
||||||
/**
|
|
||||||
* Default content slot.
|
|
||||||
* @param {Object} scope - default slot's params.
|
|
||||||
*/
|
|
||||||
default: (scope: {
|
|
||||||
/**
|
|
||||||
* Registers a form field for validation and tracking.
|
|
||||||
* @param field - The name of the form field to register.
|
|
||||||
* @param options - Configuration options for the field, such as validation rules.
|
|
||||||
* @returns - Returns an object or value representing the registered field.
|
|
||||||
*/
|
|
||||||
register: (field: string, options: any) => any;
|
|
||||||
/**
|
|
||||||
* Resets the entire form state, clearing values and validation statuses.
|
|
||||||
*/
|
|
||||||
reset: () => void;
|
|
||||||
/**
|
|
||||||
* Indicates whether the form is valid, returning `true` if all fields pass validation.
|
|
||||||
*/
|
|
||||||
valid: boolean;
|
|
||||||
/**
|
|
||||||
* Stores the state of each form field, with the field name as the key and its state as the value.
|
|
||||||
*/
|
|
||||||
states: Record<string, FormFieldState>;
|
|
||||||
}) => VNode[];
|
}) => VNode[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines valid emits in Form component.
|
* Defines valid emits in Form component.
|
||||||
*/
|
*/
|
||||||
export interface FormEmitsOptions {
|
export interface FormFieldEmitsOptions {}
|
||||||
/**
|
|
||||||
* Emitted when the form is submitted.
|
|
||||||
* @param {Event} event - Original DOM event.
|
|
||||||
*/
|
|
||||||
submit: (event: Event) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export declare type FormEmits = EmitFn<FormEmitsOptions>;
|
export declare type FormEmits = EmitFn<FormFieldEmitsOptions>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* **PrimeVue - Form**
|
* **PrimeVue - FormField**
|
||||||
*
|
*
|
||||||
* _Form provides validation functionality and manages form state._
|
* _FormField is a helper component that provides validation and tracking for form fields._
|
||||||
*
|
*
|
||||||
* [Live Demo](https://www.primevue.org/form/)
|
* [Live Demo](https://www.primevue.org/form/)
|
||||||
* --- ---
|
* --- ---
|
||||||
|
@ -271,11 +218,11 @@ export declare type FormEmits = EmitFn<FormEmitsOptions>;
|
||||||
* @group Component
|
* @group Component
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
declare const FormField: DefineComponent<FormFieldProps, FormSlots, FormEmits>;
|
declare const FormField: DefineComponent<FormFieldProps, FormFieldSlots, FormEmits>;
|
||||||
|
|
||||||
declare module 'vue' {
|
declare module 'vue' {
|
||||||
export interface GlobalComponents {
|
export interface GlobalComponents {
|
||||||
FormField: DefineComponent<FormFieldProps, FormSlots, FormEmits>;
|
FormField: DefineComponent<FormFieldProps, FormFieldSlots, FormEmits>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
|
// Form
|
||||||
|
export * from '@primevue/forms/form';
|
||||||
export { default as Form } from '@primevue/forms/form';
|
export { default as Form } from '@primevue/forms/form';
|
||||||
|
export * from '@primevue/forms/form/style';
|
||||||
export { default as FormStyle } from '@primevue/forms/form/style';
|
export { default as FormStyle } from '@primevue/forms/form/style';
|
||||||
|
|
||||||
|
// FormField
|
||||||
|
export * from '@primevue/forms/formfield';
|
||||||
export { default as FormField } from '@primevue/forms/formfield';
|
export { default as FormField } from '@primevue/forms/formfield';
|
||||||
|
export * from '@primevue/forms/formfield/style';
|
||||||
export { default as FormFieldStyle } from '@primevue/forms/formfield/style';
|
export { default as FormFieldStyle } from '@primevue/forms/formfield/style';
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
|
// Form
|
||||||
|
export * from '@primevue/forms/form';
|
||||||
export { default as Form } from '@primevue/forms/form';
|
export { default as Form } from '@primevue/forms/form';
|
||||||
|
export * from '@primevue/forms/form/style';
|
||||||
export { default as FormStyle } from '@primevue/forms/form/style';
|
export { default as FormStyle } from '@primevue/forms/form/style';
|
||||||
|
|
||||||
|
// FormField
|
||||||
|
export * from '@primevue/forms/formfield';
|
||||||
export { default as FormField } from '@primevue/forms/formfield';
|
export { default as FormField } from '@primevue/forms/formfield';
|
||||||
|
export * from '@primevue/forms/formfield/style';
|
||||||
export { default as FormFieldStyle } from '@primevue/forms/formfield/style';
|
export { default as FormFieldStyle } from '@primevue/forms/formfield/style';
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
export * from '@primeuix/form/resolvers';
|
export * from '@primeuix/forms/resolvers';
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
export * from '@primeuix/form/resolvers';
|
export * from '@primeuix/forms/resolvers';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { isArray, resolve } from '@primeuix/utils';
|
import { isArray, isNotEmpty, mergeKeys, resolve } from '@primeuix/utils';
|
||||||
import { computed, mergeProps, nextTick, onMounted, reactive, toValue, watch } from 'vue';
|
import { computed, getCurrentInstance, mergeProps, nextTick, onMounted, reactive, toValue, watch } from 'vue';
|
||||||
|
|
||||||
function tryOnMounted(fn, sync = true) {
|
function tryOnMounted(fn, sync = true) {
|
||||||
if (getCurrentInstance()) onMounted(fn);
|
if (getCurrentInstance()) onMounted(fn);
|
||||||
|
@ -34,10 +34,10 @@ export const useForm = (options = {}) => {
|
||||||
const validateOn = async (option, defaultValue) => {
|
const validateOn = async (option, defaultValue) => {
|
||||||
let results = {};
|
let results = {};
|
||||||
|
|
||||||
isArray(options[option]) ? options[option].forEach(async (field) => (results = await validate(field))) : (options[option] ?? defaultValue) && (results = await validate());
|
isArray(options[option]) ? (results = await validate(options[option])) : (options[option] ?? defaultValue) && (results = await validate());
|
||||||
const field = Object.keys(fields).find((field) => fields[field]?.options?.[option]);
|
const fieldArr = Object.keys(fields).filter((field) => fields[field]?.options?.[option]) || [];
|
||||||
|
|
||||||
field && (results = await validate(field));
|
isNotEmpty(fieldArr) && (results = await validate(fieldArr));
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
@ -113,16 +113,25 @@ export const useForm = (options = {}) => {
|
||||||
{ names: [], values: {} }
|
{ names: [], values: {} }
|
||||||
);
|
);
|
||||||
|
|
||||||
const result = (await options.resolver?.(resolverOptions)) ?? {};
|
let result = (await options.resolver?.(resolverOptions)) ?? {};
|
||||||
|
|
||||||
result.errors ??= {};
|
result.errors ??= {};
|
||||||
|
|
||||||
|
const flattenFields = [field].flat();
|
||||||
|
|
||||||
for (const [fieldName, fieldInst] of Object.entries(fields)) {
|
for (const [fieldName, fieldInst] of Object.entries(fields)) {
|
||||||
|
if (flattenFields.includes(fieldName) || !field) {
|
||||||
const fieldResolver = fieldInst.options?.resolver;
|
const fieldResolver = fieldInst.options?.resolver;
|
||||||
|
|
||||||
fieldResolver && (result.errors[fieldName] = await fieldResolver({ value: fieldInst.states.value, name: fieldName })?.errors);
|
if (fieldResolver) {
|
||||||
|
const fieldValue = fieldInst.states.value;
|
||||||
|
const fieldResult = (await fieldResolver({ values: fieldValue, value: fieldValue, name: fieldName })) ?? {};
|
||||||
|
|
||||||
|
isArray(fieldResult.errors) && (fieldResult.errors = { [fieldName]: fieldResult.errors });
|
||||||
|
|
||||||
|
result = mergeKeys(result, fieldResult);
|
||||||
|
}
|
||||||
|
|
||||||
if (fieldName === field || !field) {
|
|
||||||
const errors = result.errors[fieldName] ?? [];
|
const errors = result.errors[fieldName] ?? [];
|
||||||
//const value = result.values?.[fieldName] ?? states[sField].value;
|
//const value = result.values?.[fieldName] ?? states[sField].value;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue