FleetbaseFleetbase

Resource Context Panel Service

The `resource-context-panel` service opens contextual detail overlays for any Fleetbase resource — single-content or tabbed, with route-sync and a stack of nested panels.

Resource Context Panel Service

@service resourceContextPanel;

The resource-context-panel service is the standardized way to open a contextual detail overlay for a record. It supports a stack of panels, single-content or tabbed layouts, route-synced URLs, and per-tab navigation guards.

This is the same mechanism the console uses for "click a row → open detail panel" — and you can drive it from anywhere in your extension.

Inject

import Component from '@glimmer/component';
import { inject as service } from '@ember/service';

export default class DriverRowComponent extends Component {
  @service resourceContextPanel;
}

Open a Single-Content Panel

@action openDriver(driver) {
  this.resourceContextPanel.open({
    title: driver.name,
    resource: driver,
    content: 'driver/detail-panel',     // component path
    size: 'lg',
    onClose: () => { /* … */ },
  });
}

The component at addon/components/driver/detail-panel.{hbs,js} renders inside the panel and receives the resource via its arguments.

Open a Tabbed Panel

@action openOrder(order) {
  this.resourceContextPanel.open({
    title: order.public_id,
    resource: order,
    tabs: [
      { key: 'overview', label: 'Overview', component: 'order/tabs/overview' },
      { key: 'timeline', label: 'Timeline', component: 'order/tabs/timeline' },
      { key: 'comments', label: 'Comments', component: 'order/tabs/comments' },
    ],
    initialTab: 'overview',
    routeSync: true,
    closeOnTransition: true,
  });
}

A tabbed panel is required to have either tabs or content, not both.

Definition Object

FieldTypeDescription
idstringOptional — auto-generated if omitted
titlestringPanel title
resource (or model)modelThe Fleetbase record the panel is about
sizestringsm, md, lg, xl, full (default sm)
contentstringComponent path for a single-content panel
tabsarrayTab descriptors (mutually exclusive with content)
initialTabstringInitial tab key
routeSyncbooleanReflect the open panel + active tab in the URL via panel_id and panel_tab query params
closeOnTransitionbooleanClose automatically when the user navigates away
onOpen({ resource, model, close })Called when the panel opens
onClose({ model, close })Called when closing — return a Promise to wait

Tab Descriptor

FieldTypeDescription
keystringUnique key
label (or title)stringDisplay label
componentstringComponent path
renderfunctionAlternative — render function
beforeLeave({ model, close }) → bool | Promise<bool>Guard that runs when switching away from this tab — return false to block

Public API

MethodDescription
open(definition)Open a panel. Returns the panel ID
update(id, partial)Merge updates into an existing panel
close(id?)Close a specific panel, or the active one if no id
closeAll()Close every panel in the stack
setActiveTab(id, tabKey)Switch tabs (respects beforeLeave)
getActive()The top-most panel
getById(id)Find a specific panel
getActiveTab(id)The active tab key for a panel
isOpen(id?)Whether the panel (or any panel) is open
stack()Snapshot of the panel stack
bringToFront(id)Move a panel to the top of the stack

Route Sync

When routeSync: true, the service writes panel_id and panel_tab to the route's query params. This means refresh-survives panels and shareable URLs — paste the URL into a new browser tab and the same panel reopens.

Pair routeSync: true with closeOnTransition: true if you want the panel to close cleanly when the user navigates to a different page.

Real-World Example

@action openInvoice(invoice) {
  this.resourceContextPanel.open({
    title: `Invoice ${invoice.number}`,
    resource: invoice,
    size: 'lg',
    routeSync: true,
    closeOnTransition: true,
    tabs: [
      {
        key: 'details',
        label: 'Details',
        component: 'invoice/details',
      },
      {
        key: 'history',
        label: 'History',
        component: 'invoice/history',
      },
      {
        key: 'edit',
        label: 'Edit',
        component: 'invoice/edit',
        beforeLeave: async ({ model }) => {
          if (model.hasDirtyAttributes) {
            return confirm('Discard unsaved changes?');
          }
          return true;
        },
      },
    ],
    onClose: async ({ model }) => {
      if (model.hasDirtyAttributes) {
        model.rollbackAttributes();
      }
    },
  });
}

See Also

  • <ResourceContextPanel> component — the component the service mounts (rendered once at the app shell)
  • helpers/resource-context-panel-save-disabled.js — small helper used by the panel's save button

Source

Resource Context Panel Service | Fleetbase