@@ -103,3 +103,98 @@ function App() {
103103This feature can programmatically be controlled by pulling a React Ref either from the tree environment
104104or the tree itself, and acting on the Ref object. [ Read the documentation on externally interacting
105105with 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