[英]How to change the query imperatively in SearchKit?
我们正在尝试使用复选框创建一个默认选中所有项目的 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
注释。
我认为SearchKit的文档并不完整。 我找不到如何做到这一点。
我尝试和工作的是通过更改浏览器的 URL(设置location.href
)来更改查询,但是页面的重新加载非常难看,并且与页面其余部分的行为不匹配。
如果我没有得到任何答案,我唯一可以尝试的就是阅读三个演示的源代码,然后阅读 SearchKit 的源代码。
没有错误消息。
谢谢你。
可行的解决方案,在查看 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而不是上面代码片段中的全局变量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.