File

core/split-view/split-view.component.ts

Description

A responsive split view layout component with automatic selection management and resizable panes.

Basic usage

Example :
export class MyComponent {
  items: Device[] = [];
  selectedItem?: Device;

  onSelectionChange(item: Device | null) {
    this.selectedItem = item || undefined;
  }
}
Example :
<c8y-sv (selectionChange)="onSelectionChange($event)">
  <c8y-sv-list [title]="'Devices'">
    <c8y-sv-header-actions>
      <button class="btn btn-primary">Add Device</button>
    </c8y-sv-header-actions>

    @for (item of items; track item.id) {
      <c8y-li [c8ySvListItem]="item">
        {{ item.name }}
      </c8y-li>
    }

    <c8y-sv-footer>
      Total: {{ items.length }}
    </c8y-sv-footer>
  </c8y-sv-list>

  <c8y-sv-details
    emptyStateIcon="c8y-devices"
    emptyStateTitle="No device selected"
    emptyStateSubtitle="Select a device to view details">
    @if (selectedItem) {
      <c8y-sv-extra-header>
        <c8y-icon-panel [sections]="sections"></c8y-icon-panel>
      </c8y-sv-extra-header>
    }

    @if (selectedItem) {
      <h3>{{ selectedItem.name }}</h3>
      <p>{{ selectedItem.description }}</p>
    }
  </c8y-sv-details>
</c8y-sv>

Router-Outlet integration

For components using Angular router:

Example :
<c8y-sv>
  <c8y-alarms-list>...</c8y-alarms-list>

  <c8y-sv-details (backClick)="handleBackClick()">
    <router-outlet></router-outlet>
  </c8y-sv-details>
</c8y-sv>
Example :
async handleBackClick(): Promise<void> {
  await this.alarmsViewService.closeDetailsView(this.activatedRoute);
}

Resizable configuration

Example :
<c8y-sv
  [isResizable]="true"
  [resizableBreakpoint]="991"
  [resizableConfig]="{
    trackId: 'my-split-view',
    leftColumnWidth: '40%',
    collapseThreshold: 320,
    collapsible: false
  }"
  [initialSelection]="items[0]"
  (selectionChange)="onSelectionChange($event)">
  <!-- content -->
</c8y-sv>

List-Only mode

Omit <c8y-sv-details> for a simple list view:

Example :
<c8y-sv>
  <c8y-sv-list [title]="'Items'">
    @for (item of items; track item.id) {
      <c8y-li>{{ item.name }}</c8y-li>
    }
  </c8y-sv-list>
</c8y-sv>

Implements

OnInit OnDestroy

Metadata

Index

Properties
Methods
Inputs
Outputs
Accessors

Constructor

constructor(selectionService: SplitViewSelectionService<T>)
Parameters :
Name Type Optional
selectionService SplitViewSelectionService<T> No

Inputs

initialSelection
Type : T

Initial item to select when the component is initialized. If provided, this item will be automatically selected on component load.

Example :
<c8y-sv [initialSelection]="items[0]">
isResizable
Type : boolean
Default value : true

Enable resizable grid functionality with draggable divider. When true, users can resize the split panes by dragging the divider. Above resizableBreakpoint, the resizable grid is active. Below resizableBreakpoint, falls back to CSS-based responsive layout.

resizableBreakpoint
Type : number
Default value : 991

Minimum window width (in pixels) required for resizable grid to be active. Below this width, the component switches to a stacked mobile layout.

resizableConfig
Type : ResizableGridConfig

Configuration for resizable grid behavior.

Example :
<c8y-sv [resizableConfig]="{
  trackId: 'device-list-view',
  leftColumnWidth: '40%',
  collapseThreshold: 320,
  collapsible: false
}">
showDefaultRouterOutlet
Type : boolean
Default value : true

Whether to show a default router outlet in right-view if no right-view slot content provided.

Outputs

selectionChange
Type : EventEmitter

Emits when the selected item changes. The event emits the selected item or null when selection is cleared.

Example :
<c8y-sv (selectionChange)="onSelectionChange($event)">
Example :
onSelectionChange(item: Device | null) {
  this.selectedItem = item || undefined;
}

Methods

getContainerClasses
getContainerClasses()

Returns CSS classes for the split view container element.

Always includes: ['card', 'content-fullpage', 'grid__row--1']

Conditionally adds 'split-view--5-7' when:

  • Details component is projected
  • Resizable grid is not active (below breakpoint or disabled)
Returns : string[]

Array of CSS class names

ngOnDestroy
ngOnDestroy()
Returns : void
ngOnInit
ngOnInit()
Returns : void

Properties

Public selectionService
Type : SplitViewSelectionService<T>

Accessors

resizableConfig
getresizableConfig()
setresizableConfig(config: ResizableGridConfig)

Configuration for resizable grid behavior.

Example :
<c8y-sv [resizableConfig]="{
  trackId: 'device-list-view',
  leftColumnWidth: '40%',
  collapseThreshold: 320,
  collapsible: false
}">
Parameters :
Name Type Optional
config ResizableGridConfig No
Returns : void
hasProjectedDetails
gethasProjectedDetails()

Checks if a details component is projected.

Returns true when <c8y-sv-details> is present in the template. Returns false when <c8y-sv-details> is not present.

Returns : boolean
shouldUseResizableGrid
getshouldUseResizableGrid()

Determines if the resizable grid should be active.

Returns true when all conditions are met:

  • isResizable is true
  • Current viewport width is above resizableBreakpoint
  • Details component is projected

When false, falls back to CSS-based responsive layout.

Returns : boolean
effectiveResizableConfig
geteffectiveResizableConfig()

Returns the effective resizable configuration with all defaults applied. The configuration is memoized and updated only when inputs change.

Returns : Required<ResizableGridConfig>
<div
  [attr.aria-label]="'Split view interface' | translate"
  tabindex="-1"
  role="main"
  [ngClass]="getContainerClasses()"
  data-cy="c8y-sv"
>
  @if (shouldUseResizableGrid) {
    <c8y-resizable-grid
      [collapseThreshold]="effectiveResizableConfig.collapseThreshold"
      [collapsible]="effectiveResizableConfig.collapsible"
      [leftColumnWidth]="effectiveResizableConfig.leftColumnWidth"
      [trackId]="effectiveResizableConfig.trackId"
    >
      <div left-pane>
        <ng-container *ngTemplateOutlet="listContent"></ng-container>
      </div>
      <div right-pane>
        <ng-container *ngTemplateOutlet="detailsContent"></ng-container>
      </div>
    </c8y-resizable-grid>
  } @else {
    <ng-container *ngTemplateOutlet="listContent"></ng-container>
    <ng-container *ngTemplateOutlet="detailsContent"></ng-container>
    @if (showDefaultRouterOutlet && !hasProjectedDetails) {
      <router-outlet class="d-contents"></router-outlet>
    }
  }

  <ng-template #listContent>
    <ng-content select=":not(c8y-sv-details)"></ng-content>
  </ng-template>

  <ng-template #detailsContent>
    @if (hasProjectedDetails) {
      <ng-content select="c8y-sv-details"></ng-content>
    }
  </ng-template>
</div>

results matching ""

    No results matching ""