Browse Source

feat: add form handleCollapsedChange event (#6893)

* feat: add form handleCollapsedChange event

* fix: ts lint

* fix: ts error

---------

Co-authored-by: sqchen <chenshiqi@sshlx.com>
panda7 7 tháng trước cách đây
mục cha
commit
573637222d

+ 1 - 0
docs/src/components/common-ui/vben-form.md

@@ -335,6 +335,7 @@ useVbenForm 返回的第二个参数,是一个对象,包含了一些表单
 | handleReset | 表单重置回调 | `(values: Record<string, any>,) => Promise<void> \| void` | - |
 | handleSubmit | 表单提交回调 | `(values: Record<string, any>,) => Promise<void> \| void` | - |
 | handleValuesChange | 表单值变化回调 | `(values: Record<string, any>, fieldsChanged: string[]) => void` | - |
+| handleCollapsedChange | 表单收起展开状态变化回调 | `(collapsed: boolean) => void` | - |
 | actionButtonsReverse | 调换操作按钮位置 | `boolean` | `false` |
 | resetButtonOptions | 重置按钮组件参数 | `ActionButtonOptions` | - |
 | submitButtonOptions | 提交按钮组件参数 | `ActionButtonOptions` | - |

+ 2 - 2
packages/@core/ui-kit/form-ui/src/components/form-actions.vue

@@ -47,7 +47,7 @@ async function handleSubmit(e: Event) {
     return;
   }
 
-  const values = toRaw(await props.formApi.getValues());
+  const values = toRaw(await props.formApi.getValues()) ?? {};
   await props.handleSubmit?.(values);
 }
 
@@ -56,7 +56,7 @@ async function handleReset(e: Event) {
   e?.stopPropagation();
   const props = unref(rootProps);
 
-  const values = toRaw(await props.formApi?.getValues());
+  const values = toRaw(await props.formApi?.getValues()) ?? {};
 
   if (isFunction(props.handleReset)) {
     await props.handleReset?.(values);

+ 1 - 0
packages/@core/ui-kit/form-ui/src/form-api.ts

@@ -36,6 +36,7 @@ function getDefaultState(): VbenFormProps {
     handleReset: undefined,
     handleSubmit: undefined,
     handleValuesChange: undefined,
+    handleCollapsedChange: undefined,
     layout: 'horizontal',
     resetButtonOptions: {},
     schema: [],

+ 4 - 0
packages/@core/ui-kit/form-ui/src/types.ts

@@ -379,6 +379,10 @@ export interface VbenFormProps<
    * 表单字段映射
    */
   fieldMappingTime?: FieldMappingTime;
+  /**
+   * 表单收起展开状态变化回调
+   */
+  handleCollapsedChange?: (collapsed: boolean) => void;
   /**
    * 表单重置回调
    */

+ 1 - 1
packages/@core/ui-kit/form-ui/src/use-form-context.ts

@@ -13,7 +13,7 @@ import { useForm } from 'vee-validate';
 import { object, ZodIntersection, ZodNumber, ZodObject, ZodString } from 'zod';
 import { getDefaultsForSchema } from 'zod-defaults';
 
-type ExtendFormProps = VbenFormProps & { formApi: ExtendedFormApi };
+type ExtendFormProps = VbenFormProps & { formApi?: ExtendedFormApi };
 
 export const [injectFormProps, provideFormProps] =
   createContext<[ComputedRef<ExtendFormProps> | ExtendFormProps, FormActions]>(

+ 3 - 1
packages/@core/ui-kit/form-ui/src/vben-form.vue

@@ -40,7 +40,9 @@ const { delegatedSlots, form } = useFormInitial(props);
 provideFormProps([props, form]);
 
 const handleUpdateCollapsed = (value: boolean) => {
-  currentCollapsed.value = !!value;
+  currentCollapsed.value = value;
+  // 触发收起展开状态变化回调
+  props.handleCollapsedChange?.(value);
 };
 
 watchEffect(() => {

+ 12 - 9
packages/@core/ui-kit/form-ui/src/vben-use-form.vue

@@ -25,7 +25,7 @@ import {
 } from './use-form-context';
 // 通过 extends 会导致热更新卡死,所以重复写了一遍
 interface Props extends VbenFormProps {
-  formApi: ExtendedFormApi;
+  formApi?: ExtendedFormApi;
 }
 
 const props = defineProps<Props>();
@@ -44,11 +44,13 @@ provideComponentRefMap(componentRefMap);
 props.formApi?.mount?.(form, componentRefMap);
 
 const handleUpdateCollapsed = (value: boolean) => {
-  props.formApi?.setState({ collapsed: !!value });
+  props.formApi?.setState({ collapsed: value });
+  // 触发收起展开状态变化回调
+  forward.value.handleCollapsedChange?.(value);
 };
 
 function handleKeyDownEnter(event: KeyboardEvent) {
-  if (!state.value.submitOnEnter || !forward.value.formApi?.isMounted) {
+  if (!state?.value.submitOnEnter || !forward.value.formApi?.isMounted) {
     return;
   }
   // 如果是 textarea 不阻止默认行为,否则会导致无法换行。
@@ -58,11 +60,11 @@ function handleKeyDownEnter(event: KeyboardEvent) {
   }
   event.preventDefault();
 
-  forward.value.formApi.validateAndSubmitForm();
+  forward.value.formApi?.validateAndSubmitForm();
 }
 
 const handleValuesChangeDebounced = useDebounceFn(async () => {
-  state.value.submitOnChange && forward.value.formApi?.validateAndSubmitForm();
+  state?.value.submitOnChange && forward.value.formApi?.validateAndSubmitForm();
 }, 300);
 
 const valuesCache: Recordable<any> = {};
@@ -74,7 +76,7 @@ onMounted(async () => {
     () => form.values,
     async (newVal) => {
       if (forward.value.handleValuesChange) {
-        const fields = state.value.schema?.map((item) => {
+        const fields = state?.value.schema?.map((item) => {
           return item.fieldName;
         });
 
@@ -91,8 +93,9 @@ onMounted(async () => {
 
           if (changedFields.length > 0) {
             // 调用handleValuesChange回调,传入所有表单值的深拷贝和变更的字段列表
+            const values = await forward.value.formApi?.getValues();
             forward.value.handleValuesChange(
-              cloneDeep(await forward.value.formApi.getValues()),
+              cloneDeep(values ?? {}) as Record<string, any>,
               changedFields,
             );
           }
@@ -109,7 +112,7 @@ onMounted(async () => {
   <Form
     @keydown.enter="handleKeyDownEnter"
     v-bind="forward"
-    :collapsed="state.collapsed"
+    :collapsed="state?.collapsed"
     :component-bind-event-map="COMPONENT_BIND_EVENT_MAP"
     :component-map="COMPONENT_MAP"
     :form="form"
@@ -126,7 +129,7 @@ onMounted(async () => {
       <slot v-bind="slotProps">
         <FormActions
           v-if="forward.showDefaultActions"
-          :model-value="state.collapsed"
+          :model-value="state?.collapsed"
           @update:model-value="handleUpdateCollapsed"
         >
           <template #reset-before="resetSlotProps">