fix: option should clear when data scope change (#2800)

* fix: option should clear when data scope change

* refactor: data scope linkage in association select
This commit is contained in:
katherinehhh 2023-10-12 10:06:49 +08:00 committed by GitHub
parent ebde1b236b
commit 843677c183
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 55 additions and 11 deletions

View File

@ -1,19 +1,45 @@
import { LoadingOutlined, PlusOutlined } from '@ant-design/icons'; import { LoadingOutlined, PlusOutlined } from '@ant-design/icons';
import { RecursionField, connect, mapProps, observer, useField, useFieldSchema, useForm } from '@formily/react'; import { RecursionField, connect, mapProps, observer, useField, useFieldSchema, useForm } from '@formily/react';
import { onFieldChange, onFormInputChange } from '@formily/core';
import { uid } from '@formily/shared';
import { Space, message } from 'antd'; import { Space, message } from 'antd';
import { isFunction } from 'mathjs'; import { isFunction } from 'mathjs';
import React, { useState } from 'react'; import React, { useState, useEffect } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { RecordProvider, useAPIClient } from '../../../'; import { RecordProvider, useAPIClient } from '../../../';
import { isVariable } from '../../../variables/utils/isVariable'; import { isVariable } from '../../../variables/utils/isVariable';
import { RemoteSelect, RemoteSelectProps } from '../remote-select'; import { RemoteSelect, RemoteSelectProps } from '../remote-select';
import useServiceOptions, { useAssociationFieldContext } from './hooks'; import useServiceOptions, { useAssociationFieldContext } from './hooks';
import { getInnermostKeyAndValue } from '../../common/utils/uitls';
export type AssociationSelectProps<P = any> = RemoteSelectProps<P> & { export type AssociationSelectProps<P = any> = RemoteSelectProps<P> & {
action?: string; action?: string;
multiple?: boolean; multiple?: boolean;
}; };
export const filterAnalyses = (filters): any[] => {
if (!filters) {
return;
}
const type = Object.keys(filters)[0] || '$and';
const conditions = filters[type];
const results = [];
conditions.map((c) => {
const jsonlogic = getInnermostKeyAndValue(c);
const operator = jsonlogic?.key;
if (!operator) {
return true;
}
const regex = /\{\{\$(?:[a-zA-Z_]\w*)\.([a-zA-Z_]\w*)(?:\.id)?\}\}/;
const fieldName = jsonlogic?.value.match(regex)?.[1];
if (fieldName) {
results.push(fieldName);
}
});
return results;
};
const InternalAssociationSelect = observer((props: AssociationSelectProps) => { const InternalAssociationSelect = observer((props: AssociationSelectProps) => {
const { objectValue = true } = props; const { objectValue = true } = props;
const field: any = useField(); const field: any = useField();
@ -22,10 +48,8 @@ const InternalAssociationSelect = observer((props: AssociationSelectProps) => {
const { options: collectionField } = useAssociationFieldContext(); const { options: collectionField } = useAssociationFieldContext();
const initValue = isVariable(props.value) ? undefined : props.value; const initValue = isVariable(props.value) ? undefined : props.value;
const value = Array.isArray(initValue) ? initValue.filter(Boolean) : initValue; const value = Array.isArray(initValue) ? initValue.filter(Boolean) : initValue;
// 因为通过 Schema 的形式书写的组件,在值变更的时候 `value` 的值没有改变,所以需要维护一个 `innerValue` 来变更值 // 因为通过 Schema 的形式书写的组件,在值变更的时候 `value` 的值没有改变,所以需要维护一个 `innerValue` 来变更值
const [innerValue, setInnerValue] = useState(value); const [innerValue, setInnerValue] = useState(value);
const addMode = fieldSchema['x-component-props']?.addMode; const addMode = fieldSchema['x-component-props']?.addMode;
const isAllowAddNew = fieldSchema['x-add-new']; const isAllowAddNew = fieldSchema['x-add-new'];
const { t } = useTranslation(); const { t } = useTranslation();
@ -33,6 +57,26 @@ const InternalAssociationSelect = observer((props: AssociationSelectProps) => {
const form = useForm(); const form = useForm();
const api = useAPIClient(); const api = useAPIClient();
const resource = api.resource(collectionField.target); const resource = api.resource(collectionField.target);
const linkageFields = filterAnalyses(field.componentProps?.service?.params?.filter);
useEffect(() => {
const id = uid();
form.addEffects(id, () => {
linkageFields?.forEach((v) => {
if (v) {
onFieldChange(v, () => {
if (field.value) {
props.onChange(null);
setInnerValue(null);
}
});
}
});
});
return () => {
form.removeEffects(id);
};
}, []);
const handleCreateAction = async (props) => { const handleCreateAction = async (props) => {
const { search: value, callBack } = props; const { search: value, callBack } = props;

View File

@ -151,13 +151,13 @@ export default function useServiceOptions(props) {
}, },
} }
: null, : null,
params?.filter && value?.length // params?.filter && value?.length
? { // ? {
[fieldNames?.value]: { // [fieldNames?.value]: {
['$in']: value, // ['$in']: value,
}, // },
} // }
: null, // : null,
], ],
'$or', '$or',
); );

View File

@ -184,7 +184,7 @@ const InternalRemoteSelect = connect(
} }
const valueOptions = const valueOptions =
(v != null && (Array.isArray(v) ? v : [{ ...v, [fieldNames.value]: v[fieldNames.value] || v }])) || []; (v != null && (Array.isArray(v) ? v : [{ ...v, [fieldNames.value]: v[fieldNames.value] || v }])) || [];
return uniqBy(data?.data?.concat(valueOptions) || [], fieldNames.value); return uniqBy(data?.data?.concat(valueOptions ?? []), fieldNames.value);
}, [value, defaultValue, data?.data, fieldNames.value]); }, [value, defaultValue, data?.data, fieldNames.value]);
const onDropdownVisibleChange = (visible) => { const onDropdownVisibleChange = (visible) => {
setOpen(visible); setOpen(visible);