Skip to content

5.x migration guide

Grigas.Petraitis edited this page Mar 6, 2024 · 6 revisions

The 5.0 release of @itwin/presentation-components package is all about filtering and its integration with other components.

  • The PresentationInstanceFilterDialog and PresentationInstanceFilterBuilder used by the dialog received some major improvements to improve their usability and integration with other components.
  • The PresentationTreeRenderer and PresentationTreeNodeRenderer now provide much better UX for filtering and limiting the size of hierarchy levels.

This page documents all breaking changes in @itwin/presentation-components@^5.0.0.

Dependencies

  • #412: Bumped peer dependency version of all itwinjs-core packages to ^4.4.0.
  • #399: Bumped peer dependency version of all appui packages to ^4.9.0.
  • #398: Bumped @itwin/itwinui-react package dependency version to 3.x. This entails that all components from @itwin/presentation-components must be wrapped in ThemeProvider from itwinui-react@3. See more.

Breaking changes

Tree

  • #222: Show the size of filtered tree hierarchy level while building a filter.

    Includes breaking @beta API change in PresentationTreeRenderer - instead of taking IModelConnection, TreeModelSource and ITreeNodeLoader as 3 separate props, it now takes a single AbstractTreeNodeLoaderWithProvider<IPresentationTreeDataProvider> prop. Implementing the feature required adding an IPresentationTreeDataProvider to props, however requesting a single, more specific, node loader instead of 4 different props that are tightly coupled was a much cleaner solution, especially since using PresentationTreeRenderer with node loaders other than AbstractTreeNodeLoaderWithProvider<IPresentationTreeDataProvider> made little sense.

    Generally, reacting to the change is as simple as removing imodel and modelSource from the list of props, passed to PresentationTreeRenderer. In case the type of nodeLoader prop doesn't match, we recommend using the new usePresentationTreeState for creating one. Or, if the tree is not based on presentation rules, not using the PresentationTreeRenderer at all and instead switching to TreeRenderer.

  • #313: Added interactive and more detailed informational messages in the tree and its hierarchy level filtering components:

    • When a hierarchy level size exceeds given limit, a message is displayed, suggesting the results should be filtered to reduce the result set.
    • The hierarchy level filtering dialog informs whether provided filters reduce the result set to a small enough size to be displayed in the tree.

    Includes 2 breaking @beta API changes:

    • PresentationTreeNodeRenderer now takes onClearFilterClick and onFilterClick callback props with node identifier argument rather than PresentationTreeNodeItem. This was a necessary change to allow opening filtering dialog for a parent node from its child node. To react to this breaking change:

      before

      const [clickedNode, setClickedNode] = useState<PresentationTreeNodeItem>();
      <PresentationTreeNodeRenderer
        {...nodeProps}
        onFilterClick={(node: PresentationTreeNodeItem) => {
          setClickedNode(node);
        }}
      />;

      after

      const [clickedNode, setClickedNode] = useState<PresentationTreeNodeItem>();
      <PresentationTreeNodeRenderer
        {...nodeProps}
        onFilterClick={(nodeId: string) => {
          const node = modelSource.getModel().getNode(nodeId);
          if (isTreeModelNode(node) && isPresentationTreeNodeItem(node.item)) {
            setClickedNode(node.item);
          }
        }}
      />;
    • useHierarchyLevelFiltering hook's result now contains functions applyFilter and clearFilter that take node identifier argument rather than a TreeNodeItem. The change was made to help reacting to the above PresentationTreeNodeRenderer change by requiring the same types of arguments as what onClearFilterClick and onFilterClick get. In case these functions are used outside of PresentationTreeNodeRenderer workflows, reacting to the breaking change is as follows:

      before

      const { applyFilter } = useHierarchyLevelFiltering({ nodeLoader, modelSource });
      const [filterNode, setFilterNode] = useState<PresentationTreeNodeItem>();
      const onFilterChanged = (filter: PresentationInstanceFilterInfo) => {
        if (filterNode) {
          applyFilter(filterNode, filter);
        }
      };

      after

      const { applyFilter } = useHierarchyLevelFiltering({ nodeLoader, modelSource });
      const [filterNodeId, setFilterNodeId] = useState<string>();
      const onFilterChanged = (filter: PresentationInstanceFilterInfo) => {
        if (filterNodeId) {
          applyFilter(filterNodeId, filter);
        }
      };

    Generally, the above two APIs are used together, which means no changes should be necessary.

Instance filter builder / dialog

  • #438: Changed PresentationInstanceFilterDialogProps.descriptor attribute to propertiesSource, which associates Descriptor with input keys used to create the descriptor. This allows the dialog to use the Keys information, which is required for loading suggestions in value inputs.

    before

    const [inputKeys] = useState<Keys>();
    <PresentationInstanceFilterDialog
      descriptor={async () => loadDescriptor(inputKeys)}
    />;

    after

    const [inputKeys] = useState<Keys>();
    <PresentationInstanceFilterDialog
      propertiesSource={async () => {
        const descriptor = await loadDescriptor(inputKeys);
        return { descriptor, inputKeys };
      }}
    />

New features

Instance filter builder / dialog

  • #316: Promoted some @internal APIs to @beta:

    • useInstanceFilterPropertyInfos - a hook for creating a property list based on supplied Descriptor. The property list is necessary for rendering the PropertyFilterBuilder component.
    • PresentationInstanceFilter.fromComponentsPropertyFilter - for adding presentation data to PropertyFilter built by usePropertyFilterBuilder.
    • PresentationInstanceFilter.toComponentsPropertyFilter - for stripping out presentation data from filter for usage with usePropertyFilterBuilder.
    • PresentationFilterBuilderValueRenderer - a custom renderer for property value input. It renders unique values selector for Equal / NotEqual rules and handles numeric values' unit conversion on top of the general value input.
    • PresentationInstanceFilterPropertyInfo - a data structure defining a property used in instance filter.
  • #316, #407: Added utilities PresentationInstanceFilter.fromGenericInstanceFilter and PresentationInstanceFilter.toGenericInstanceFilter to help with parsing the PresentationInstanceFilter data structure into a more consumer-friendly, lower-level GenericInstanceFilter.

  • #193: Show a validation error message when entered property value is invalid.

  • #176: Added unique values selector when using Equal or Not Equal operators. The component provides a drop-down of values available for selected property.

    • null values are omitted. "Is Null" and "Is Not Null" operators should be used instead.
    • For empty non null values Empty Value option is shown in selector.
  • #356: UX enhancements:

    • Changed the "Apply" button to always be enabled, even when no filtering rules are selected. In such situations, the calling component may clear the filter.
    • Added a "Reset" button which clears all the filtering rules in the dialog.
    • Added a toolbarButtonsRenderer prop to allow rendering custom toolbar buttons at the bottom of the dialog.
  • #447: Added ability to pass initial filter as a callback that will be invoked when descriptor is loaded.

  • #358: Show a union of properties of selected classes rather than intersection.

  • #416: PresentationInstanceFilterDialog now allows applying filter when only classes are selected.

    Added createInstanceFilterDefinition that creates InstanceFilterDefinition from PresentationInstanceFilterInfo. Created definition can be passed to PresentationManager to filter results when creating content or hierarchies.

Tree

  • #388: Adjust API of PresentationTreeRenderer by separating PresentationTreeRenderer hierarchy level filtering logic into useFilterablePresentationTree hook.

  • #421: Simplify / clarify PresentationTree and PresentationTreeRenderer APIs.

    • Change PresentationTreeProps.treeRenderer type to make it compatible with what PresentationTreeRenderer expects.

      before

      <PresentationTree
        {...props}
        state={state}
        treeRenderer={(treeProps) => (
          <PresentationTreeRenderer
            {...treeProps}
            nodeLoader={state.nodeLoader}
          />
        )}
      />

      after

      <PresentationTree
        {...props}
        state={state}
        treeRenderer={(treeProps) => (
          <PresentationTreeRenderer {...treeProps} />
        )}
      />
    • Removed nodeRenderer prop from PresentationTreeRendererProps. The prop is not used by PresentationTreeRenderer as it always uses its own PresentationTreeNodeRenderer to render nodes.

Property grid

  • #305: Added an editor for editing values of properties with quantity / units information.

    Editor works only if there is SchemaMetadataContextProvider in React component tree above property grid components. Otherwise simple numeric editor is used.

    // somewhere at the global level
    import { IModelConnection } from "@itwin/core-frontend";
    import { SchemaContext } from "@itwin/ecschema-metadata";
    function getIModelSchemaContext(imodel: IModelConnection): SchemaContext {
      // return a cached instance of SchemaContext for given IModelConnection
    }
    
    // in the component render function
    <SchemaMetadataContextProvider
      imodel={imodel}
      schemaContextProvider={getIModelSchemaContext}
    >
      <VirtualizedPropertyGridWithDataProvider {...props} />
    </SchemaMetadataContextProvider>;

New deprecations

  • convertToInstanceFilterDefinition - use PresentationInstanceFilter.toInstanceFilterDefinition instead.
  • isPresentationInstanceFilterConditionGroup - use PresentationInstanceFilter.isConditionGroup instead.
  • NavigationPropertyEditor and NavigationPropertyTargetEditor - these components should not be used directly. Instead, they should be used though the PropertyEditorManager system where they're automatically registered as a default editor for all StandardTypeNames.Navigation properties.