如何在react-querybuilder中过滤FieldSelector选项

问题描述 投票:0回答:1

我正在尝试从 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)这些字段不会显示在其规则字段选择器中,因为它们已被过滤掉!

因此,看起来在添加新规则时,应该对其进行过滤,以便该规则不会出现这些选项。

如有任何帮助,我们将不胜感激。

javascript reactjs typescript query-builder
1个回答
0
投票

下面的字段选择器将不允许选择在同级规则(即同一组内的规则)中选择的字段,除非该规则已选择该字段。

// 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

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.