core/split-view/split-view.component.ts
A responsive split view layout component with automatic selection management and resizable panes.
export class MyComponent {
items: Device[] = [];
selectedItem?: Device;
onSelectionChange(item: Device | null) {
this.selectedItem = item || undefined;
}
}<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>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>async handleBackClick(): Promise<void> {
await this.alarmsViewService.closeDetailsView(this.activatedRoute);
}<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>Omit <c8y-sv-details> for a simple list view:
<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>
OnInit
OnDestroy
| providers |
SplitViewSelectionService
|
| selector | c8y-sv |
| standalone | true |
| imports |
CommonModule
RouterOutlet
C8yTranslatePipe
ResizableGridComponent
|
| templateUrl | ./split-view.component.html |
Properties |
|
Methods |
Inputs |
Outputs |
Accessors |
constructor(selectionService: SplitViewSelectionService<T>)
|
||||||
|
Parameters :
|
| isResizable |
Type : boolean
|
Default value : true
|
|
Enable resizable grid functionality with draggable divider.
When |
| 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 : |
| showDefaultRouterOutlet |
Type : boolean
|
Default value : true
|
|
Whether to show a default router outlet in right-view if no right-view slot content provided. |
| ngOnDestroy |
ngOnDestroy()
|
|
Returns :
void
|
| ngOnInit |
ngOnInit()
|
|
Returns :
void
|
| Public selectionService |
Type : SplitViewSelectionService<T>
|
| resizableConfig | ||||||
getresizableConfig()
|
||||||
setresizableConfig(config: ResizableGridConfig)
|
||||||
|
Configuration for resizable grid behavior. Example :
Parameters :
Returns :
void
|
| hasProjectedDetails |
gethasProjectedDetails()
|
|
Checks if a details component is projected. Returns
Returns :
boolean
|
| shouldUseResizableGrid |
getshouldUseResizableGrid()
|
|
Determines if the resizable grid should be active. Returns
When
Returns :
boolean
|
<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>