根据您的反馈添加新答案,因为这个答案与另一个答案非常不同。我即将发布的 v5.0react-querybuilder具有我在另一个答案的第一段中提到的功能。这使得实现期望的结果更加直接,并且还消除了对外部状态管理(即 Redux)的需要。
TL;DR:此处的工作代码和框示例(使用react-querybuilder@5.0.0-alpha.2)。
React Query Builder 只需要一个fieldsprops,但您可以将字段组织成一个选项组数组,而不是一个平面数组。我将operators每个字段的属性设置为默认运算符,并针对字段类型(文本与数字)进行适当过滤。
import { Field, OptionGroup } from 'react-querybuilder';
import { nameOperators, numberOperators } from './operators';
export const fields: OptionGroup<Field>[] = [
{
label: 'Names',
options: [
{ name: 'firstName', label: 'First Name', operators: nameOperators },
{ name: 'lastName', label: 'Last Name', operators: nameOperators },
],
},
{
label: 'Numbers',
options: [
{ name: 'height', label: 'Height', operators: numberOperators },
{ name: 'weight', label: 'Weight', operators: numberOperators },
],
},
];
接下来,我设置了一个自定义字段选择器组件,以仅允许属于同一选项组的字段。因此,如果选择了“名称”字段,则用户只能选择其他“名称”字段。
const FilteredFieldSelector = (props: FieldSelectorProps) => {
const filteredFields = fields.find((optGroup) =>
optGroup.options.map((og) => og.name).includes(props.value!)
)!.options;
return <ValueSelector {...{ ...props, options: filteredFields }} />;
};
这个自定义的添加规则按钮为每个调用带有选项组作为上下文的handleOnClickprops的选项组呈现一个单独的按钮。label
const AddRuleButtons = (props: ActionWithRulesAndAddersProps) => (
<>
{fields
.map((og) => og.label)
.map((lbl) => (
<button onClick={(e) => props.handleOnClick(e, lbl)}>
+Rule ({lbl})
</button>
))}
</>
);
然后context将 传递给onAddRule回调,该回调根据上下文值确定field要分配的内容。
const onAddRule = (
rule: RuleType,
_pP: number[],
_q: RuleGroupType,
context: string
) => ({
...rule,
context,
field: fields.find((optGroup) => optGroup.label === context)!.options[0].name,
});
把它们放在QueryBuilderprops中,瞧:
export default function App() {
const [query, setQuery] = useState(initialQuery);
return (
<div>
<QueryBuilder
fields={fields}
query={query}
onQueryChange={(q) => setQuery(q)}
controlElements={{
addRuleAction: AddRuleButtons,
fieldSelector: FilteredFieldSelector,
}}
onAddRule={onAddRule}
/>
<pre>{formatQuery(query, 'json')}</pre>
</div>
);
}