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.
Grundlegende Integration
Abschnitt betitelt „Grundlegende Integration“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; }}Reaktiver Status mit Signals
Abschnitt betitelt „Reaktiver Status mit Signals“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; }}Widget als Injectable Service
Abschnitt betitelt „Widget als Injectable Service“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' }); }}Cobrowsing-Zustimmung
Abschnitt betitelt „Cobrowsing-Zustimmung“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 (SSR)
Abschnitt betitelt „Angular Universal (SSR)“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; }}