fix(association-select): filter without data scope not work (#1509)
* fix(association-select): filter without data scope not work * fix: update * fix: use merge filter * refactor: better logic * fix: option has hidden * fix: hidden, disabled * fix: update * fix: merge filter doesn't handle array
This commit is contained in:
parent
ecf618783e
commit
15d067120d
@ -18,7 +18,11 @@ export type SharedFilterContextValue = {
|
||||
};
|
||||
|
||||
export const mergeFilter = (filters: any[], op = '$and') => {
|
||||
const items = filters.filter(Boolean);
|
||||
const items = filters.filter((f) => {
|
||||
if (f && typeof f === 'object' && !Array.isArray(f)) {
|
||||
return Object.values(f).filter((v) => v !== undefined).length;
|
||||
}
|
||||
});
|
||||
if (items.length === 0) {
|
||||
return {};
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { useFieldSchema } from '@formily/react';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { useFormBlockContext } from '../../../block-provider';
|
||||
import { mergeFilter } from '../../../block-provider/SharedFilterProvider';
|
||||
import { useCollection, useCollectionManager } from '../../../collection-manager';
|
||||
import { useRecord } from '../../../record-provider';
|
||||
|
||||
@ -10,7 +12,6 @@ export default function useServiceOptions(props) {
|
||||
const { getField } = useCollection();
|
||||
const { getCollectionFields } = useCollectionManager();
|
||||
const record = useRecord();
|
||||
const recordValue = record[fieldSchema.name];
|
||||
|
||||
const normalizeValues = useCallback(
|
||||
(obj) => {
|
||||
@ -23,15 +24,15 @@ export default function useServiceOptions(props) {
|
||||
);
|
||||
|
||||
const value = useMemo(() => {
|
||||
if (recordValue === undefined || recordValue === null) {
|
||||
if (props.value === undefined || props.value === null) {
|
||||
return;
|
||||
}
|
||||
if (Array.isArray(recordValue)) {
|
||||
return recordValue.map(normalizeValues);
|
||||
if (Array.isArray(props.value)) {
|
||||
return props.value.map(normalizeValues);
|
||||
} else {
|
||||
return normalizeValues(recordValue);
|
||||
return [normalizeValues(props.value)];
|
||||
}
|
||||
}, [recordValue, normalizeValues]);
|
||||
}, [props.value, normalizeValues]);
|
||||
|
||||
const collectionField = useMemo(() => {
|
||||
return getField(fieldSchema.name);
|
||||
@ -40,20 +41,18 @@ export default function useServiceOptions(props) {
|
||||
const sourceValue = record?.[collectionField?.sourceKey];
|
||||
const filter = useMemo(() => {
|
||||
const isOToAny = ['oho', 'o2m'].includes(collectionField?.interface);
|
||||
return {
|
||||
$or: [
|
||||
{
|
||||
$and: [
|
||||
isOToAny
|
||||
? {
|
||||
[collectionField.foreignKey]: {
|
||||
$is: null,
|
||||
},
|
||||
}
|
||||
: null,
|
||||
params?.filter,
|
||||
],
|
||||
},
|
||||
return mergeFilter(
|
||||
[
|
||||
mergeFilter([
|
||||
isOToAny
|
||||
? {
|
||||
[collectionField.foreignKey]: {
|
||||
$is: null,
|
||||
},
|
||||
}
|
||||
: null,
|
||||
params?.filter,
|
||||
]),
|
||||
isOToAny && sourceValue !== undefined && sourceValue !== null
|
||||
? {
|
||||
[collectionField.foreignKey]: {
|
||||
@ -61,15 +60,16 @@ export default function useServiceOptions(props) {
|
||||
},
|
||||
}
|
||||
: null,
|
||||
value
|
||||
params?.filter && value
|
||||
? {
|
||||
[fieldNames.value]: {
|
||||
[Array.isArray(value) ? '$in' : '$eq']: value,
|
||||
['$in']: value,
|
||||
},
|
||||
}
|
||||
: null,
|
||||
],
|
||||
};
|
||||
'$or',
|
||||
);
|
||||
}, [params?.filter, getCollectionFields, collectionField, sourceValue, value, fieldNames.value]);
|
||||
|
||||
return useMemo(() => {
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { LoadingOutlined } from '@ant-design/icons';
|
||||
import { connect, mapProps, mapReadPretty } from '@formily/react';
|
||||
import { SelectProps } from 'antd';
|
||||
import Item from 'antd/lib/list/Item';
|
||||
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
|
||||
import { ResourceActionOptions, useRequest } from '../../../api-client';
|
||||
import { mergeFilter } from '../../../block-provider/SharedFilterProvider';
|
||||
import { useCompile } from '../../hooks';
|
||||
import { defaultFieldNames, Select } from '../select';
|
||||
import { ReadPretty } from './ReadPretty';
|
||||
@ -30,9 +32,7 @@ const InternalRemoteSelect = connect(
|
||||
...service?.params,
|
||||
// fields: [fieldNames.label, fieldNames.value, ...(service?.params?.fields || [])],
|
||||
// search needs
|
||||
filter: {
|
||||
$and: [service?.params?.filter].filter(Boolean),
|
||||
},
|
||||
filter: mergeFilter([service?.params?.filter]),
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -59,27 +59,39 @@ const InternalRemoteSelect = connect(
|
||||
|
||||
const onSearch = async (search) => {
|
||||
run({
|
||||
filter: {
|
||||
$and: [
|
||||
{
|
||||
[fieldNames.label]: {
|
||||
$includes: search,
|
||||
},
|
||||
filter: mergeFilter([
|
||||
{
|
||||
[fieldNames.label]: {
|
||||
$includes: search,
|
||||
},
|
||||
service?.params?.filter,
|
||||
].filter(Boolean),
|
||||
},
|
||||
},
|
||||
service?.params?.filter,
|
||||
]),
|
||||
});
|
||||
};
|
||||
|
||||
const getOptionsByFieldNames = useCallback(
|
||||
(item) => {
|
||||
return Object.keys(fieldNames).reduce((obj, key) => {
|
||||
const value = item[fieldNames[key]];
|
||||
if (value) {
|
||||
// support hidden, disabled, etc.
|
||||
obj[['label', 'value', 'options'].includes(key) ? fieldNames[key] : key] =
|
||||
key === 'label' ? compile(value) : value;
|
||||
}
|
||||
return obj;
|
||||
}, {} as any);
|
||||
},
|
||||
[fieldNames],
|
||||
);
|
||||
const normalizeOptions = useCallback(
|
||||
(obj) => {
|
||||
if (objectValue || typeof obj === 'object') {
|
||||
return { ...obj, [fieldNames.label]: compile(obj[fieldNames.label]) };
|
||||
return getOptionsByFieldNames(obj);
|
||||
}
|
||||
return { [fieldNames.value]: obj, [fieldNames.label]: obj };
|
||||
},
|
||||
[objectValue, fieldNames.value],
|
||||
[objectValue, getOptionsByFieldNames],
|
||||
);
|
||||
|
||||
const options = useMemo(() => {
|
||||
@ -90,13 +102,8 @@ const InternalRemoteSelect = connect(
|
||||
: [normalizeOptions(value)]
|
||||
: [];
|
||||
}
|
||||
return (
|
||||
data?.data?.map((item) => ({
|
||||
...item,
|
||||
[fieldNames.label]: compile(item[fieldNames.label]),
|
||||
})) || []
|
||||
);
|
||||
}, [data, fieldNames.label, objectValue, value]);
|
||||
return data?.data?.map(getOptionsByFieldNames) || [];
|
||||
}, [data?.data, getOptionsByFieldNames, normalizeOptions, value]);
|
||||
|
||||
const onDropdownVisibleChange = () => {
|
||||
if (firstRun.current) {
|
||||
|
Loading…
Reference in New Issue
Block a user