Creating Dashboards

When creating a workflow in deephaven.ui, components are laid out in a panel and those panels are then laid out in a dashboard.

The dashboard is the top-level component that allows you to create a page layout containing a collection of components. The user can move and resize panels within the dashboard in rows, columns, and stacks.

In the previous section, we went over the important rules of dashboards and the basics of how to lay out panels in a dashboard with ui.row, ui.column, and ui.stack. This section covers more advanced topics.

Layout Hierarchy

Top-Level

Your dashboard must start with a row or column, which is the “top” of the layout tree. Columns should go inside rows, and rows should go inside columns.

Note: Nesting rows within rows or columns within columns will sub-divide the row or column.

Bottom-Level

Stacks and panels are considered the “bottom” of the layout tree. Once added, the layout in that section is considered complete. For layouts within a panel, see tabs, flex, grid, view, and nested dashboards.

Automatic Wrapping

Children are implicitly wrapped when necessary, so the entire layout does not need to be explicitly defined.

End to end example: dashboard([t1, t2]) would become dashboard(column(stack(panel(t1)), stack(panel(t2)))).

Automatic wrapping is applied by the following rules:

  1. Dashboard: wrap in row/column if no single node is the default. For example, [t1, t2] as the child to the dashboard would become row(t1, t2).
  2. Row/Column:
    • If there are children that are rows/columns, wrap the non-wrapped children with the same element. For example, row(col(t1), t2) becomes row(col(t1), col(t2)).
    • If none of the children are wrapped by rows/columns, they are wrapped in stacks. For example, row(col(t1), col(t2)) from above becomes row(col(stack(t1)), col(stack(t2))).
  3. Stacks: wrap non-panel children in panels. For example, row(col(stack(t1)), col(stack(t2))) becomes row(col(stack(panel(t1))), col(stack(panel(t2)))).

Multiple dashboards

To create multiple dashboards, you can return more than one dashboard from your script.

Sharing state between multiple panels in a dashboard

As deephaven.ui components are spread across multiple panels in a dashboard, those components will need to interact and respond to changes in components in different panels. This means sharing state between components.

In the sections on sharing state, we learned to “lift state up” to a common parent in order to share it between multiple components. However, one of the rules of a dashboard is that it must be a child of the root script and not nested inside a @ui.component. This means that state cannot be lifted up into a component that returns a dashboard.

How, then, do we lift state up to share it between panels in a dashboard? A ui.row or a ui.column can be returned from a @ui.component containing state for the dashboard.

In the example, create_dashboard contains the state variables shared across multiple panels. It then returns a ui.row which is used as the root layout for a dashboard. This allows the UI elements in the control_panel component to apply a filter to table and plot located in separate panels.

Nested Dashboards

Dashboards can be nested inside panels to create complex layouts with isolated drag-and-drop regions. Each nested dashboard has its own independent layout that users can rearrange without affecting the parent dashboard.

Unlike root-level dashboards, nested dashboards can be returned from @ui.component functions, making them ideal for creating reusable dashboard components with encapsulated state.

Basic nested dashboard

A nested dashboard is created by placing a ui.dashboard inside a ui.panel:

Nested dashboard component with state

Nested dashboards are particularly effective when combined with @ui.component to create stateful, reusable dashboard sections

Sharing state between nested dashboards

State can be shared between nested dashboards by lifting state up to a common parent component. This allows multiple nested dashboards to react to the same state changes:

In this example, connected_dashboards holds the shared filter_text state. Both filter_dashboard and results_dashboard receive this state as props. When the user types in the filter input, both nested dashboards update to reflect the new filter value.

Key considerations for nested dashboards

  1. Isolation: Panels within a nested dashboard can only be dragged within that nested dashboard. Cross-dashboard drag-and-drop is not supported.
  2. State persistence: Each nested dashboard maintains its own layout state. When the page is reloaded, the arrangement of panels within nested dashboards is preserved.
  3. Performance: Each nested dashboard creates its own layout instance. For most use cases this has negligible impact, but consider the complexity when creating many nested dashboards.