Setting up a Tree component for Unified Selection

As described in the Tree selection handling section, selection in a Tree component and Unified Selection are synchronized in a two-way manner:

  • When a tree node is selected, ECInstances it represents are added to unified selection.
  • When an ECInstance is added to unified selection, the nodes that represent that ECInstance are selected in the tree component.

Reference

The Reference section in Unified Selection page describes the core APIs used in Unified Selection workflows.

The @itwin/presentation-components package delivers some helper APIs to make setting up Tree components to work with Unified Selection easier:

  • useUnifiedSelectionTreeEventHandler hook is here for majority of the situations. It merely creates the default UnifiedSelectionTreeEventHandler and makes sure it's disposed when necessary.

  • UnifiedSelectionTreeEventHandler is expected to be used directly in more advanced situations - when the tree component handles not only nodes' expand/collapse and selection, but also some custom actions that need to be implemented in a custom handler. In this situation consumers are expected to take care of creating and disposing their event handler on their own.

Example

The below example shows how to create a very basic presentation rules driven Tree component and hook it into Unified Selection. The latter part is achieved by using useUnifiedSelectionTreeEventHandler to create a tree event handler, as opposed to using the general useTreeEventsHandler.

function MyTree(props: { imodel: IModelConnection }) {
  // create a node loader for given iModel and ruleset
  const state = usePresentationTreeState({
    imodel: props.imodel,
    ruleset,
    pagingSize: 10,
    // create a tree events handler that synchronizes tree nodes' selection with unified selection
    eventHandlerFactory: useCallback(
      (eventHandlerProps: PresentationTreeEventHandlerProps) => new UnifiedSelectionTreeEventHandler({ nodeLoader: eventHandlerProps.nodeLoader }),
      [],
    ),
  });

  // width and height should generally we computed using ResizeObserver API or one of its derivatives
  const [width] = useState(400);
  const [height] = useState(600);

  if (!state) {
    return null;
  }

  return <PresentationTree width={width} height={height} state={state} selectionMode={SelectionMode.Extended} />;
}

Last Updated: 05 March, 2024