Setting up iTwin.js Presentation library

Before the Presentation library can be used, it needs to be properly initialized. Because of the nature of iTwin.js architecture, the library needs to be initialized on the backend and each frontend that is in use — just like the iTwin.js framework itself.

Backend

There are 2 main steps to enable Presentation library usage:

  1. Register PresentationRpcInterface when initializing IModelHost. The way it's done depends on IModelHost specialization, but in any case that's similar to how any other RpcInterface is registered. A couple of examples:

    • For a web app, IModelHost has to be initialized first and required RPC interfaces need to be passed to BentleyCloudRpcManager.initializeImpl:

      import { PresentationRpcInterface } from "@itwin/presentation-common";
      const rpcInterfaces = [...otherRpcInterfaces, PresentationRpcInterface];
      
      // initialize IModelHost
      await IModelHost.startup();
      
      // tell BentleyCloudRpcManager which RPC interfaces to handle
      const rpcConfig = BentleyCloudRpcManager.initializeImpl({ info: { title: "presentation-test-app", version: "v1.0" } }, rpcInterfaces);
      
      // create a basic express web server
      const port = Number(process.env.PORT || 3001);
      const server = new IModelJsExpressServer(rpcConfig.protocol);
      await server.initialize(port);
      
    • For an Electron app, required RPC interfaces are passed straight into ElectronHost.startup:

      import { PresentationRpcInterface } from "@itwin/presentation-common";
      const rpcInterfaces = [...otherRpcInterfaces, PresentationRpcInterface];
      
      const electronHost: ElectronHostOptions = {
        webResourcesPath: path.join(__dirname, "..", "..", "..", "build"),
        rpcInterfaces,
        developmentServer: process.env.NODE_ENV === "development",
        ipcHandlers: [SampleIpcHandler],
      };
      const iModelHost: IModelHostOptions = {};
      
      let authClient;
      if (process.env.IMJS_OIDC_ELECTRON_TEST_CLIENT_ID && process.env.IMJS_OIDC_ELECTRON_TEST_REDIRECT_URI && process.env.IMJS_OIDC_ELECTRON_TEST_SCOPES) {
        authClient = new ElectronMainAuthorization({
          clientId: process.env.IMJS_OIDC_ELECTRON_TEST_CLIENT_ID,
          redirectUri: process.env.IMJS_OIDC_ELECTRON_TEST_REDIRECT_URI,
          scope: process.env.IMJS_OIDC_ELECTRON_TEST_SCOPES,
        });
        iModelHost.authorizationClient = authClient;
      }
      
      await ElectronHost.startup({ electronHost, iModelHost });
      if (authClient)
        await authClient.signInSilent();
      await ElectronHost.openMainWindow();
      
  2. Initialize Presentation backend:

    import { Presentation, PresentationProps } from "@itwin/presentation-backend";
    // set up props for the presentation backend
    const presentationBackendProps: PresentationProps = {
      rulesetDirectories: [path.join("assets", "presentation_rules")],
    };
    // initialize presentation backend
    Presentation.initialize(presentationBackendProps);
    

Frontend

Similar to the backend, the frontend initialization consists of 2 steps:

  1. Register PresentationRpcInterface when initializing IModelApp. That's done by making sure the interface is included into the list of rpcInterfaces when calling startup on IModelApp or one of its specializations.

    import { PresentationRpcInterface } from "@itwin/presentation-common";
    const rpcInterfaces = [...otherRpcInterfaces, PresentationRpcInterface];
    const iModelAppOpts: IModelAppOptions = {
      rpcInterfaces,
    };
    await ElectronApp.startup({ iModelApp: iModelAppOpts });
    

    Note: The above example uses ElectronApp, but it's similar with other specializations like WebViewerApp.

  2. Initialize Presentation frontend:

    import { createFavoritePropertiesStorage, DefaultFavoritePropertiesStorageTypes, Presentation } from "@itwin/presentation-frontend";
    await Presentation.initialize({
      presentation: {
        // specify locale for localizing presentation data, it can be changed afterwards
        activeLocale: IModelApp.localization.getLanguageList()[0],
    
        // specify the preferred unit system
        activeUnitSystem: "metric",
      },
      favorites: {
        storage: createFavoritePropertiesStorage(DefaultFavoritePropertiesStorageTypes.UserPreferencesStorage),
      },
    });
    

Last Updated: 30 November, 2023