【问题标题】:How to change the query imperatively in SearchKit?如何在 SearchKit 中强制更改查询?
【发布时间】:2021-01-14 00:49:12
【问题描述】:

我们正在尝试创建一个带有复选框的 RefinementListFilter,默认情况下所有项目都选中,当用户取消选中所有项目时,所有项目都会自动选中。我们完成了类似的事情,但它有问题(抱歉,如果代码感觉难看,它是 WIP):

在渲染代码中

<RefinementListFilter
  id="type"
  title="By Type"
  field="_type"
  size={10}
  operator="OR"
  itemComponent={RefinementOption}
  listComponent={RefinementList}
/>

其他代码

/**
 * Returns the label associated to a data type
 * @param {string} val
 */
const valueToLabel = (val) => {
  const data = [
    { label: 'Documents', value: 'document' },
    { label: 'Links', value: 'link' },
    { label: 'Web Pages', value: 'article' },
    { label: 'Species Info', value: 'species' },
    { label: 'Habitat Types Info', value: 'habitat' },
    { label: 'Sites Info', value: 'site' },
    { label: 'Protected Area', value: 'protected_area' }, // hidden
  ];
  return data.filter((x) => x.value === val)[0].label;
};

/**
 * Displays a checkbox w/ a label that replaces the default data type string.
 * @param {object} props
 */
const RefinementOption = (props) => {
  return (
    <div
      role="checkbox"
      onKeyPress={() => {}}
      className={props.bemBlocks
        .option()
        .state({ selected: props.active })
        .mix(props.bemBlocks.container('item'))}
      tabIndex={0}
      aria-checked={props.active}
    >
      <label style={{ flexGrow: 1 }}>
        <input
          type="checkbox"
          onClick={(...args) => {
            return props.onClick(...args);
          }}
          checked={props.active}
          className="sk-item-list-option__checkbox"
        />
        <span className={props.bemBlocks.option('text')}>
          {valueToLabel(props.label)}
        </span>
      </label>
      {/* <div className={props.bemBlocks.option('count')}>{props.count}</div> */}
    </div>
  );
};

/**
 * Before showing the data types' filter sort its options well and the default
 * behavior is to all be checked (this is the same as when all are unchecked,
 * because the implicit operator is OR).
 * @param {object} props
 */
const RefinementList = (props) => {
  const data = [
    { order: 1, key: 'document' },
    { order: 2, key: 'link' },
    { order: 3, key: 'article' },
    { order: 4, key: 'species' },
    { order: 5, key: 'habitat' },
    { order: 6, key: 'site' },
    { order: 7, key: 'protected_area' }, // hidden
  ];

  let arr = [...props.items];
  arr = arr.filter((x) => x.key !== 'protected_area');
  arr = arr.sort((a, b) => {
    console.log('A', a.key, 'B', b.key);

    const ai = data.findIndex((x) => x.key === a.key);
    const bi = data.findIndex((x) => x.key === b.key);
    if (ai < 0 || isNaN(ai) || bi < 0 || isNaN(bi)) {
      return 0;
    }

    return data[ai].order - data[bi].order;
  });

  const allKeys = arr.map((x) => x.key);
  const activeCount = props.selectedItems.length;
  let selectedItems = props.selectedItems.map((x) => x.key);
  if (activeCount === 0) {
    selectedItems = allKeys;
  } else {
    selectedItems = props.selectedItems;
    if (selectedItems.length === allKeys.length) {
      selectedItems = [];

      // TODO: do this in the selected filters view w/o reloading the page
      const newLoc = window.location.href
        .replace(/type\[\d+\]=[a-zA-Z0-9_]+/g, '')
        .replace(/&&/g, '&')
        .replace(/\?&/g, '?')
        .replace(/[&?]$/, '');
      if (newLoc !== window.location.href) {
        window.location.href = newLoc;
      }
    }
  }

  return (
    <CheckboxItemList {...props} items={arr} selectedItems={selectedItems} />
  );
};

我们试图避免出现在上面代码中的TODO 注释中。

documentation of SearchKit 在我看来并不完整。我找不到如何做到这一点。

我尝试和工作的是通过更改浏览器的 URL(设置location.href)来更改查询,但是页面的重新加载确实很难看,并且与页面其余部分的行为不匹配。

如果我没有得到任何答案,我唯一可以尝试的就是阅读三个演示的源代码,然后阅读 SearchKit 的源代码。

the relevant file 的 Git 存储库是 OSS。

没有错误消息。

谢谢。

【问题讨论】:

    标签: javascript reactjs searchkit


    【解决方案1】:

    工作解决方案,在查看了 SearchKit 源代码之后(是的,第一行是一个全局变量,我将来可能会将其更改为其他内容):

    let globalSearchKitManagers = [];
    

    ...

    for (const sk of globalSearchKitManagers) {
      if (typeof sk !== 'undefined') {
        const filters = sk.accessors.accessors.filter(
          (x) => x.field === '_type',
        );
        for (const x of filters) {
          sk.removeAccessor(x);
        }
        sk.performSearch(true, true);
      }
    }
    

    ...

    React.useEffect(() => {
      globalSearchKitManagers.push(searchkit);
      return () => {
        globalSearchKitManagers.splice(
          globalSearchKitManagers.indexOf(searchkit),
          1,
        );
      };
    }, [searchkit]);
    

    更新:我们现在使用SearchkitComponent,而不是上面代码sn-p中的全局变量。

    【讨论】:

      猜你喜欢
      • 2023-04-04
      • 2021-10-07
      • 1970-01-01
      • 2012-08-12
      • 1970-01-01
      • 2022-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多