Modern Angular leverages Standalone Components,Signals, and
direct DOM injection via createComponent and
ViewContainerRef. This guide covers clean, zero-boilerplate integration with Strelit
UI Kit.
1. Installation
Add Strelit UI Kit to your Angular project dependencies:
npm install strelit-ui-kit
2. Standalone Docking Host Component
Create an Angular component that initializes Strelit and mounts standalone Angular components dynamically into Strelit containers:
import {
Component,
ElementRef,
viewChild,
OnInit,
OnDestroy,
ApplicationRef,
createComponent,
EnvironmentInjector,
Type,
} from '@angular/core';
import { StrelitLayout, LayoutConfig, ComponentContainer } from 'strelit-ui-kit';
import { TelemetryPanelComponent } from './telemetry-panel.component';
import { LogStreamPanelComponent } from './log-stream-panel.component';
@Component({
selector: 'app-docking-workspace',
standalone: true,
template: `<div #dockingContainer class="docking-viewport"></div>`,
styles: [
`
.docking-viewport {
width: 100vw;
height: 100vh;
overflow: hidden;
}
`,
],
})
export class DockingWorkspaceComponent implements OnInit, OnDestroy {
private containerEl = viewChild.required<ElementRef<HTMLDivElement>>('dockingContainer');
private layout?: StrelitLayout;
private registry: Record<string, Type<any>> = {
telemetry: TelemetryPanelComponent,
logs: LogStreamPanelComponent,
};
constructor(
private appRef: ApplicationRef,
private injector: EnvironmentInjector
) {}
ngOnInit() {
const config: LayoutConfig = {
root: {
type: 'row',
content: [
{
type: 'component',
componentType: 'angularHost',
title: 'Telemetry Inspector',
componentState: { componentKey: 'telemetry' },
},
{
type: 'component',
componentType: 'angularHost',
title: 'Event Log Stream',
componentState: { componentKey: 'logs' },
},
],
},
};
// 1. Instantiate StrelitLayout directly on target element
this.layout = new StrelitLayout(this.containerEl().nativeElement);
// 2. Register dynamic Angular Component factory
this.layout.registerComponentFactoryFunction(
'angularHost',
(container: ComponentContainer, itemConfig) => {
const targetEl = container.element;
const state = (itemConfig.componentState as { componentKey: string }) || {
componentKey: '',
};
const ComponentClass = this.registry[state.componentKey];
if (!ComponentClass) return;
// Instantiate standalone component dynamically
const compRef = createComponent(ComponentClass, {
environmentInjector: this.injector,
hostElement: targetEl,
});
this.appRef.attachView(compRef.hostView);
// Clean up Angular component lifecycle when pane is closed
container.on('destroy', () => {
this.appRef.detachView(compRef.hostView);
compRef.destroy();
});
}
);
// 3. Load layout configuration
this.layout.loadLayout(config);
}
ngOnDestroy() {
this.layout?.destroy();
}
}
3. Reactive State with Angular Signals
Inside your standalone panels, you can use Angular Signals freely. State changes will re-render within their docked panel instantly without triggering unnecessary global change-detection cycles:
import { Component, signal, computed } from '@angular/core';
@Component({
selector: 'app-telemetry-panel',
standalone: true,
template: `
<div class="telemetry-box">
<h4>Throughput: {{ throughput() }} req/s</h4>
<p>Status: {{ statusLabel() }}</p>
<button (click)="increment()">Simulate Traffic Spike</button>
</div>
`,
})
export class TelemetryPanelComponent {
throughput = signal(1240);
statusLabel = computed(() => (this.throughput() > 2000 ? 'High Load 🔥' : 'Nominal 🟢'));
increment() {
this.throughput.update((v) => v + 250);
}
}
Looking for legacy AngularJS 1.x tutorials?
For historical projects maintaining AngularJS 1.x codebases with $scope, see our
Simple AngularJS and
Complex AngularJS guides in the Archival section.