feat(@vben-core/form-ui): add typed form value codecs (#8189)
* feat(@vben-core/form-ui): add typed form value codecs * test(@vben-core/form-ui): cover codec value boundaries * refactor(project): propagate form codec generics * feat(@vben/plugins): propagate form codecs through vxe grids * refactor(@vben/playground): migrate form codec examples * refactor(@vben/playground): migrate query forms to codecs * docs(@vben/docs): document form value codecs
This commit is contained in:
@@ -3,6 +3,7 @@ import type { VxeGridInstance } from 'vxe-table';
|
||||
import type {
|
||||
BaseFormComponentType,
|
||||
ExtendedFormApi,
|
||||
FormValues,
|
||||
} from '@vben-core/form-ui';
|
||||
|
||||
import type { VxeGridProps } from './types';
|
||||
@@ -34,14 +35,16 @@ export class VxeGridApi<
|
||||
T extends Record<string, any> = any,
|
||||
D extends BaseFormComponentType = BaseFormComponentType,
|
||||
P extends Record<string, any> = Record<never, never>,
|
||||
TFormValues extends FormValues = FormValues,
|
||||
TSubmitValues extends FormValues = TFormValues,
|
||||
> {
|
||||
public formApi = {} as ExtendedFormApi;
|
||||
public formApi = {} as ExtendedFormApi<TFormValues, D, P, TSubmitValues>;
|
||||
|
||||
// private prevState: null | VxeGridProps = null;
|
||||
public grid = {} as VxeGridInstance<T>;
|
||||
public state: null | VxeGridProps<T, D, P> = null;
|
||||
public state: null | VxeGridProps<T, D, P, TFormValues, TSubmitValues> = null;
|
||||
|
||||
public store: Store<VxeGridProps<T, D, P>>;
|
||||
public store: Store<VxeGridProps<T, D, P, TFormValues, TSubmitValues>>;
|
||||
|
||||
/**
|
||||
* 已读行 helper(在 mount 中初始化,业务能力全部封装在 useViewedRow 中)
|
||||
@@ -52,12 +55,26 @@ export class VxeGridApi<
|
||||
|
||||
private stateHandler: StateHandler;
|
||||
|
||||
constructor(options: VxeGridProps<T, D, P> = {} as VxeGridProps<T, D, P>) {
|
||||
constructor(
|
||||
options: VxeGridProps<
|
||||
T,
|
||||
D,
|
||||
P,
|
||||
TFormValues,
|
||||
TSubmitValues
|
||||
> = {} as VxeGridProps<T, D, P, TFormValues, TSubmitValues>,
|
||||
) {
|
||||
const storeState = { ...options };
|
||||
|
||||
const defaultState = getDefaultState();
|
||||
this.store = new Store<VxeGridProps<T, D, P>>(
|
||||
mergeWithArrayOverride(storeState, defaultState) as VxeGridProps<T, D, P>,
|
||||
this.store = new Store<VxeGridProps<T, D, P, TFormValues, TSubmitValues>>(
|
||||
mergeWithArrayOverride(storeState, defaultState) as VxeGridProps<
|
||||
T,
|
||||
D,
|
||||
P,
|
||||
TFormValues,
|
||||
TSubmitValues
|
||||
>,
|
||||
);
|
||||
|
||||
this.store.subscribe((state) => {
|
||||
@@ -106,7 +123,10 @@ export class VxeGridApi<
|
||||
this.viewedRowHelper?.markAsViewed(record);
|
||||
}
|
||||
|
||||
mount(instance: null | VxeGridInstance, formApi: ExtendedFormApi) {
|
||||
mount(
|
||||
instance: null | VxeGridInstance,
|
||||
formApi: ExtendedFormApi<TFormValues, D, P, TSubmitValues>,
|
||||
) {
|
||||
if (!this.isMounted && instance) {
|
||||
this.grid = instance;
|
||||
this.formApi = formApi;
|
||||
@@ -138,7 +158,11 @@ export class VxeGridApi<
|
||||
this.viewedRowHelper?.removeKeys(keys);
|
||||
}
|
||||
|
||||
setGridOptions(options: Partial<VxeGridProps<T, D, P>['gridOptions']>) {
|
||||
setGridOptions(
|
||||
options: Partial<
|
||||
VxeGridProps<T, D, P, TFormValues, TSubmitValues>['gridOptions']
|
||||
>,
|
||||
) {
|
||||
this.setState({
|
||||
gridOptions: options,
|
||||
});
|
||||
@@ -154,8 +178,10 @@ export class VxeGridApi<
|
||||
|
||||
setState(
|
||||
stateOrFn:
|
||||
| ((prev: VxeGridProps<T, D, P>) => Partial<VxeGridProps<T, D, P>>)
|
||||
| Partial<VxeGridProps<T, D, P>>,
|
||||
| ((
|
||||
prev: VxeGridProps<T, D, P, TFormValues, TSubmitValues>,
|
||||
) => Partial<VxeGridProps<T, D, P, TFormValues, TSubmitValues>>)
|
||||
| Partial<VxeGridProps<T, D, P, TFormValues, TSubmitValues>>,
|
||||
) {
|
||||
if (isFunction(stateOrFn)) {
|
||||
this.store.setState((prev) => {
|
||||
|
||||
@@ -10,7 +10,11 @@ import type { Ref } from 'vue';
|
||||
|
||||
import type { ClassType, DeepPartial } from '@vben/types';
|
||||
|
||||
import type { BaseFormComponentType, VbenFormProps } from '@vben-core/form-ui';
|
||||
import type {
|
||||
BaseFormComponentType,
|
||||
FormValues,
|
||||
VbenFormProps,
|
||||
} from '@vben-core/form-ui';
|
||||
|
||||
import type { VxeGridApi } from './api';
|
||||
|
||||
@@ -124,6 +128,8 @@ export interface VxeGridProps<
|
||||
T extends Record<string, any> = any,
|
||||
D extends BaseFormComponentType = BaseFormComponentType,
|
||||
P extends Record<string, any> = Record<never, never>,
|
||||
TFormValues extends FormValues = FormValues,
|
||||
TSubmitValues extends FormValues = TFormValues,
|
||||
> {
|
||||
/**
|
||||
* 数据
|
||||
@@ -156,7 +162,7 @@ export interface VxeGridProps<
|
||||
/**
|
||||
* 表单配置
|
||||
*/
|
||||
formOptions?: VbenFormProps<D, P>;
|
||||
formOptions?: VbenFormProps<D, P, TFormValues, TSubmitValues>;
|
||||
/**
|
||||
* 显示搜索表单
|
||||
*/
|
||||
@@ -175,9 +181,13 @@ export type ExtendedVxeGridApi<
|
||||
D extends Record<string, any> = any,
|
||||
F extends BaseFormComponentType = BaseFormComponentType,
|
||||
P extends Record<string, any> = Record<never, never>,
|
||||
> = VxeGridApi<D, F, P> & {
|
||||
useStore: <S = NoInfer<VxeGridProps<D, F, P>>>(
|
||||
selector?: (state: NoInfer<VxeGridProps<D, F, P>>) => S,
|
||||
TFormValues extends FormValues = FormValues,
|
||||
TSubmitValues extends FormValues = TFormValues,
|
||||
> = VxeGridApi<D, F, P, TFormValues, TSubmitValues> & {
|
||||
useStore: <S = NoInfer<VxeGridProps<D, F, P, TFormValues, TSubmitValues>>>(
|
||||
selector?: (
|
||||
state: NoInfer<VxeGridProps<D, F, P, TFormValues, TSubmitValues>>,
|
||||
) => S,
|
||||
) => Readonly<Ref<S>>;
|
||||
};
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { VxeGridSlots, VxeGridSlotTypes } from 'vxe-table';
|
||||
|
||||
import type { SlotsType } from 'vue';
|
||||
|
||||
import type { BaseFormComponentType } from '@vben-core/form-ui';
|
||||
import type { BaseFormComponentType, FormValues } from '@vben-core/form-ui';
|
||||
|
||||
import type { ExtendedVxeGridApi, VxeGridProps } from './types';
|
||||
|
||||
@@ -23,24 +23,28 @@ export function useVbenVxeGrid<
|
||||
T extends Record<string, any> = any,
|
||||
D extends BaseFormComponentType = BaseFormComponentType,
|
||||
P extends Record<string, any> = Record<never, never>,
|
||||
>(options: VxeGridProps<T, D, P>) {
|
||||
TFormValues extends FormValues = FormValues,
|
||||
TSubmitValues extends FormValues = TFormValues,
|
||||
>(options: VxeGridProps<T, D, P, TFormValues, TSubmitValues>) {
|
||||
// const IS_REACTIVE = isReactive(options);
|
||||
const api = new VxeGridApi<T, D, P>(options);
|
||||
const extendedApi: ExtendedVxeGridApi<T, D, P> = api as ExtendedVxeGridApi<
|
||||
T,
|
||||
D,
|
||||
P
|
||||
>;
|
||||
const api = new VxeGridApi<T, D, P, TFormValues, TSubmitValues>(options);
|
||||
const extendedApi: ExtendedVxeGridApi<T, D, P, TFormValues, TSubmitValues> =
|
||||
api as ExtendedVxeGridApi<T, D, P, TFormValues, TSubmitValues>;
|
||||
extendedApi.useStore = (selector) => {
|
||||
return useStore(api.store, selector);
|
||||
};
|
||||
|
||||
const Grid = defineComponent(
|
||||
(props: VxeGridProps<T, D, P>, { attrs, slots }) => {
|
||||
(
|
||||
props: VxeGridProps<T, D, P, TFormValues, TSubmitValues>,
|
||||
{ attrs, slots },
|
||||
) => {
|
||||
onBeforeUnmount(() => {
|
||||
api.unmount();
|
||||
});
|
||||
api.setState({ ...props, ...attrs } as Partial<VxeGridProps<T, D, P>>);
|
||||
api.setState({ ...props, ...attrs } as Partial<
|
||||
VxeGridProps<T, D, P, TFormValues, TSubmitValues>
|
||||
>);
|
||||
return () =>
|
||||
h(
|
||||
VxeGrid,
|
||||
@@ -48,7 +52,7 @@ export function useVbenVxeGrid<
|
||||
...props,
|
||||
...attrs,
|
||||
api: extendedApi as ExtendedVxeGridApi,
|
||||
},
|
||||
} as any,
|
||||
slots,
|
||||
);
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user