我正在尝试从 FieldSelector 中删除我已经使用过的字段。
我有一个 FieldSelector 的自定义组件,假设 A、B、C、D、E 是 FieldSelector 组件中可用的总字段。如果我使用了 A 和 B,则当单击“添加规则”按钮时,这些不应包含在新规则中。添加新规则后,新规则的字段选择器应该只有 C、D、E 选项。
如何实现这一目标?
这是我的代码。
<QueryBuilderAntD>
<QueryBuilder
fields={fields} // All fields are being passed here e.g. A, B, C, D, E
query={query}
listsAsArrays
combinators={[{ name: 'and', label: 'AND' }]}
validator={defaultValidator}
controlElements={{
addGroupAction: () => null,
addRuleAction: AddRuleAction,
removeRuleAction: makeRemoveRuleAction(fields),
valueEditor: CustomValueEditor,
combinatorSelector: CombinatorSelector,
operatorSelector: OperatorSelector,
fieldSelector: FieldSelector,
}}
disabled={isDisabled}
/>
</QueryBuilderAntD>
这是我的添加规则按钮组件:
export const AddRuleAction = (props: AntDActionProps) =>
props.level > 1 ? null : (
<Button size="lg" variant="success" onClick={(d) => props.handleOnClick(d)} disabled={props.disabled}>
<PlusIcon className="mr-2" /> Rule
</Button>
)
这是字段选择组件:
const FieldSelector = (props: FieldSelectorProps) => {
const { control, setValue, getValues } = useFormContext()
const namePrefix = `${name}[${props.path[0]}]`
const rules = getValues(name);
const usedRules = new Set(rules?.map((rule: RuleType) => rule.field));
filteredOptions = filterUsedRules(props.options as FullOption[], rules)
return (
<div className="flex">
<FormField
control={control}
name={`${namePrefix}.field`}
rules={{ required: true }}
render={({ field }) => (
<Select
value={field.value}
onValueChange={(d) => {
props.handleOnChange(d)
field.onChange(d)
if (props.value !== d) {
setValue(`${namePrefix}.value`, [], { shouldDirty: true })
}
}}
disabled={props.disabled}
>
<SelectTrigger className="h-10 min-w-[120px] w-fit">
<SelectValue placeholder={props.value} data-testid="qb-field-selector" />
</SelectTrigger>
<SelectContent side="bottom">
{props.options?.map((p: BaseOption, index: number) => (
<SelectItem key={index} value={`${p.value}`}>
{p.label}
</SelectItem>
))}
</SelectContent>
</Select>
)}
/>
</div>
)
}
我尝试过滤掉使用的规则(取自本地状态)并从 props.options 中删除那些规则,但是我已经使用过的字段(例如 A、B)这些字段不会显示在其规则字段选择器中,因为它们已被过滤掉!
因此,看起来在添加新规则时,应该对其进行过滤,以便该规则不会出现这些选项。
如有任何帮助,我们将不胜感激。
下面的字段选择器将不允许选择在同级规则(即同一组内的规则)中选择的字段,除非该规则已选择该字段。
// src/FieldSelector.tsx
import type { FullField, RuleGroupType, FieldSelectorProps } from 'react-querybuilder';
import {
ValueSelector,
findPath,
getParentPath,
getQuerySelectorById,
useQueryBuilderSelector,
isRuleGroup,
} from 'react-querybuilder';
export const FieldSelector = (props: FieldSelectorProps) => {
// Get the full query from RQB store
const query = useQueryBuilderSelector(
getQuerySelectorById(props.schema.qbId)
);
// On initial render `query` will be undefined, so just bail out.
if (!query) return null;
// Get the list of fields selected in sibling rules
const siblingFields = (
findPath(getParentPath(props.path), query) as RuleGroupType
).rules.map(r => (isRuleGroup(r) ? '' : r.field));
// Define the list of acceptable fields for this rule. Filter out any
// already-selected fields except if it matches this rule's field.
const thisRuleFields = (props.options as FullField[]).filter(
({ name }) => name === props.value || !siblingFields.includes(name)
);
// Render the default value selector with the same props except
// for the option list.
return <ValueSelector {...props} options={thisRuleFields} />;
};
这里可能有助于用户体验的一件事是在
autoSelectField={false}
道具上设置 <QueryBuilder />
。
这是一个使用该组件的工作沙箱:https://codesandbox.io/p/devbox/6yhlvl?file=%2Fsrc%2FFieldSelector.tsx