Skip to content

Commit 93f7c19

Browse files
committed
feat: finder doc (#287)
1 parent 3b90567 commit 93f7c19

File tree

1 file changed

+95
-0
lines changed

1 file changed

+95
-0
lines changed

packages/docs/docs/guides/search.mdx

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,98 @@ function App() {
103103
This feature can programmatically be controlled by pulling a React Ref either from the tree environment
104104
or the tree itself, and acting on the Ref object. [Read the documentation on externally interacting
105105
with the tree via Refs](/docs/guides/refs) to find out more.
106+
107+
## Finding items that are not loaded in
108+
109+
The search functionality only searches through items that are currently visible in the tree. This keeps the
110+
functionality in par with similar tree implementations, where you can directly type into a tree to jump to already
111+
available items, giving an easier way to scroll through large trees.
112+
113+
Searching through all items and expanding potentially hidden items to expose the searched item is a bit more complicated,
114+
and depends on your data structure to work. Because there are several ways to define a data structure with RCT,
115+
it is up to you to implement the logic to actually find the item that should be displayed. Once you determined a path
116+
to the item (i.e. an array of item ids), you can use the `expandSubsequently(treeId, path)` function in the
117+
[Tree environment ref](/docs/api/interfaces/TreeEnvironmentRef) to expand the tree to the searched item, or use
118+
the `expandSubsequently(path)` function in the [Tree Ref](/docs/api/interfaces/TreeRef).
119+
120+
Try entering "blackberry" in the example below, and clicking on "Find item":
121+
122+
```jsx live
123+
export const CustomFinder = () => {
124+
const [search, setSearch] = useState('');
125+
const tree = useRef(null)
126+
127+
const dataProvider = useMemo(
128+
() =>
129+
new StaticTreeDataProvider(longTree.items, (item, data) => ({
130+
...item,
131+
data,
132+
})),
133+
[]
134+
);
135+
136+
const findItemPath = useCallback(
137+
async (search, searchRoot = 'root') => {
138+
const item = await dataProvider.getTreeItem(searchRoot);
139+
if (item.data.toLowerCase().includes(search.toLowerCase())) {
140+
return [item.index];
141+
}
142+
const searchedItems = await Promise.all(
143+
item.children?.map(child => findItemPath(search, child)) ?? []
144+
);
145+
const result = searchedItems.find(item => item !== null);
146+
if (!result) {
147+
return null;
148+
}
149+
return [item.index, ...result];
150+
},
151+
[dataProvider]
152+
);
153+
154+
const find = useCallback(
155+
e => {
156+
e.preventDefault();
157+
if (search) {
158+
findItemPath(search).then(path => {
159+
if (path) {
160+
tree.current
161+
?.expandSubsequently(path.slice(0, path.length - 1))
162+
.then(() => {
163+
tree.current?.selectItems([path[path.length - 1]]);
164+
tree.current?.focusItem(path[path.length - 1]);
165+
});
166+
}
167+
});
168+
}
169+
},
170+
[findItemPath, search]
171+
);
172+
173+
return (
174+
<>
175+
<form onSubmit={find}>
176+
<input
177+
value={search}
178+
onChange={e => setSearch(e.target.value)}
179+
placeholder="Search..."
180+
/>
181+
<button type="submit">Find item</button>
182+
</form>
183+
<UncontrolledTreeEnvironment<string>
184+
dataProvider={dataProvider}
185+
getItemTitle={item => item.data}
186+
viewState={{
187+
'tree-1': {},
188+
}}
189+
>
190+
<Tree
191+
treeId="tree-1"
192+
rootItem="root"
193+
treeLabel="Tree Example"
194+
ref={tree}
195+
/>
196+
</UncontrolledTreeEnvironment>
197+
</>
198+
);
199+
};
200+
```

0 commit comments

Comments
 (0)