Zum Inhalt springen

Angular-Integrationsleitfaden

Dieser Leitfaden behandelt Muster zur Integration des Univerx Client SDK in Angular-Anwendungen, einschließlich reaktivem State-Management und Angular Universal (SSR) Überlegungen.

Erstellen und zerstören Sie die Widget-Instanz mithilfe der ngOnInit- und ngOnDestroy-Lifecycle-Hooks. Implementieren Sie OnDestroy, um eine Bereinigung zu garantieren, wenn die Komponente entfernt wird.

import { Component, OnInit, OnDestroy } from '@angular/core';
import { WidgetClient } from '@univerx/client-sdk';
@Component({
selector: 'app-support-widget',
template: '', // SDK renders its own UI
})
export class SupportWidgetComponent implements OnInit, OnDestroy {
private widget: WidgetClient | null = null;
ngOnInit(): void {
this.widget = new WidgetClient({
widgetKey: 'your-widget-key',
onAgentAssigned: (agent) => console.log(`Agent: ${agent.name}`),
onCallEnded: () => this.widget?.destroy(),
});
this.widget.init();
}
ngOnDestroy(): void {
this.widget?.destroy();
this.widget = null;
}
}

Für Angular 17+ Anwendungen, die Signals verwenden, stellen Sie den Widget-Status als Signal bereit, damit Ihr Template automatisch reagiert:

import { Component, OnInit, OnDestroy, signal } from '@angular/core';
import { WidgetClient, WidgetState, Agent } from '@univerx/client-sdk';
@Component({
selector: 'app-support-widget',
standalone: true,
template: `
@if (state() === 'ready') {
<button (click)="joinQueue()">Get support</button>
}
@if (state() === 'queued') {
<p>Queue position: {{ queuePosition() }}</p>
}
@if (state() === 'in_call') {
<button (click)="endCall()">End call</button>
}
`,
})
export class SupportWidgetComponent implements OnInit, OnDestroy {
private widget: WidgetClient | null = null;
state = signal<WidgetState>('idle');
queuePosition = signal<number | null>(null);
currentAgent = signal<Agent | null>(null);
ngOnInit(): void {
this.widget = new WidgetClient({
widgetKey: 'your-widget-key',
onReady: () => this.state.set('ready'),
onCallStarted: () => this.state.set('in_call'),
onCallEnded: () => this.state.set('ended'),
});
this.widget.on('queue:update', (position) => this.queuePosition.set(position));
this.widget.on('queue:left', () => this.queuePosition.set(null));
this.widget.on('agent:assigned', (agent) => this.currentAgent.set(agent));
this.widget.init();
}
async joinQueue(): Promise<void> {
await this.widget?.joinQueue({ terms: true });
this.state.set('queued');
}
async endCall(): Promise<void> {
await this.widget?.endSession();
}
ngOnDestroy(): void {
this.widget?.destroy();
this.widget = null;
}
}

Für Anwendungen, die die Widget-Instanz über mehrere Komponenten hinweg teilen müssen, wrappen Sie es in einen Angular-Service:

import { Injectable, OnDestroy } from '@angular/core';
import { WidgetClient, WidgetConfig, WidgetState } from '@univerx/client-sdk';
import { BehaviorSubject } from 'rxjs';
@Injectable({ providedIn: 'root' })
export class WidgetService implements OnDestroy {
private widget: WidgetClient | null = null;
readonly state$ = new BehaviorSubject<WidgetState>('idle');
readonly queuePosition$ = new BehaviorSubject<number | null>(null);
init(config: WidgetConfig): void {
if (this.widget) return; // already initialised
this.widget = new WidgetClient({
...config,
onReady: () => this.state$.next('ready'),
onCallStarted: () => this.state$.next('in_call'),
onCallEnded: () => this.state$.next('ended'),
});
this.widget.on('queue:update', (pos) => this.queuePosition$.next(pos));
this.widget.on('queue:left', () => this.queuePosition$.next(null));
this.widget.init();
}
async joinQueue(consents?: Record<string, boolean>) {
return this.widget?.joinQueue(consents);
}
async endSession() {
return this.widget?.endSession();
}
ngOnDestroy(): void {
this.widget?.destroy();
this.widget = null;
}
}

Injizieren Sie den Service wo benötigt:

import { Component, OnInit } from '@angular/core';
import { WidgetService } from './widget.service';
@Component({
selector: 'app-root',
template: `...`,
})
export class AppComponent implements OnInit {
constructor(public widgetService: WidgetService) {}
ngOnInit(): void {
this.widgetService.init({ widgetKey: 'your-widget-key' });
}
}

Behandeln Sie Cobrowsing-Zustimmung, indem Sie auf das Event lauschen und den Komponenten-Status aktualisieren:

this.widget.on('cobrowse:consent:required', ({ accept, decline }) => {
// Store handlers and show your consent dialog
this.cobrowseHandlers = { accept, decline };
this.showConsentDialog = true;
});

Angular Universal rendert Komponenten auf dem Server, wo window und document nicht verfügbar sind. Schützen Sie alle SDK-Instanziierungen mit isPlatformBrowser:

import { Component, OnInit, OnDestroy, Inject, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
import { WidgetClient } from '@univerx/client-sdk';
@Component({
selector: 'app-support-widget',
template: '',
})
export class SupportWidgetComponent implements OnInit, OnDestroy {
private widget: WidgetClient | null = null;
constructor(@Inject(PLATFORM_ID) private platformId: object) {}
ngOnInit(): void {
if (!isPlatformBrowser(this.platformId)) return;
this.widget = new WidgetClient({ widgetKey: 'your-widget-key' });
this.widget.init();
}
ngOnDestroy(): void {
this.widget?.destroy();
this.widget = null;
}
}