This library lets you easily add chat widget functionality to your Angular application, whether you have an account on livechat.com or text.com. This package supports both the LiveChat and Text widgets.
Using npm:
npm install @livechat/widget-angularor using yarn:
yarn add @livechat/widget-angularIf you have an account on livechat.com, use the livechat-widget component and provide your license number:
// app.module.ts
import { NgModule } from '@angular/core'
import { LiveChatWidgetModule } from '@livechat/widget-angular'
@NgModule({
/* ... */
imports: [LiveChatWidgetModule],
})
export class AppModule {}// app.component.ts
import { Component } from '@angular/core'
import { EventHandlerPayload } from '@livechat/widget-angular'
@Component({
/* ... */
templateUrl: './app.component.html',
})
export class AppComponent {
handleNewEvent(event: EventHandlerPayload<'onNewEvent'>) {
console.log('LiveChatWidget.onNewEvent', event)
}
}<!-- app.component.html -->
<livechat-widget
license="12345678"
visibility="maximized"
(onNewEvent)="handleNewEvent($event)"
></livechat-widget>If you have an account on text.com, use the text-widget component and provide your organizationId:
// app.module.ts
import { NgModule } from '@angular/core'
import { LiveChatWidgetModule } from '@livechat/widget-angular'
@NgModule({
/* ... */
imports: [LiveChatWidgetModule],
})
export class AppModule {}// app.component.ts
import { Component } from '@angular/core'
import { EventHandlerPayload } from '@livechat/widget-angular'
@Component({
/* ... */
templateUrl: './app.component.html',
})
export class AppComponent {
handleNewEvent(event: EventHandlerPayload<'onNewEvent'>) {
console.log('TextWidget.onNewEvent', event)
}
}<!-- app.component.html -->
<text-widget
organizationId="614fe72f-3319-43c6-9ae6-c410c65df230"
visibility="maximized"
(onNewEvent)="handleNewEvent($event)"
></text-widget>All properties described below are used for initialization on the first render and later updates of the chat widget with new values on change.
| Prop | Type |
|---|---|
| license / organizationId | string (required) |
| customerName | string |
| group | string |
| customerEmail | string |
| chatBetweenGroups | boolean |
| sessionVariables | Record<string, string> |
| visibility | 'maximized' | 'minimized' | 'hidden' |
| customIdentityProvider | () => CustomerAuth |
CustomerAuth:
| parameters | type | description |
|---|---|---|
| getFreshToken | () => Promise | Should resolve with freshly requested customer access token. |
| getToken | () => Promise | Should resolve with currently stored customer access token. |
| hasToken | () => Promise | Should resolve with a boolean value representing if a token has been already acquired. |
| invalidate | () => Promise | Should handle token invalidation and/or clearing the locally cached value. |
All event handlers listed below are registered if provided for the first time. They unregister on the component cleanup or the property value change. Descriptions of all events are available after clicking on the associated links.
- onReady
- onAvailabilityChanged
- onVisibilityChanged
- onCustomerStatusChanged
- onNewEvent
- onFormSubmitted
- onRatingSubmitted
- onGreetingDisplayed
- onGreetingHidden
- onRichMessageButtonClicked
The LiveChatWidgetModule, exported from this package, registers a set of injectable services. All of them expose a subscribable BehaviorSubject instance. It allows consuming reactive data from the chat widget in any place of the application, as long as the LiveChatWidget or TextWidget component is rendered in the tree.
Access the current chat widget availability or visibility state if the chat widget is loaded.
// app.component.ts
import { Component, OnInit } from '@angular/core'
import {
WidgetStateService,
WidgetStateSubject,
} from '@livechat/widget-angular'
@Component({
/* ... */
templateUrl: './app.component.html',
})
export class AppComponent implements OnInit {
widgetState$: WidgetStateSubject
constructor(widgetStateService: WidgetStateService) {
this.widgetState$ = widgetStateService.subject
}
ngOnInit() {
this.widgetState$.subscribe((widgetState) => {
console.log('AppComponent.ngOnInit.widgetState', widgetState)
})
}
}<!-- app.component.html -->
<div *ngIf="widgetState$ | async as widgetState">
<div>{{ widgetState.availability }}</div>
<div>{{ widgetState.visibility }}</div>
</div>Check if the chat widget is ready using the boolean flag isWidgetReady.
// app.component.ts
import { Component, OnInit } from '@angular/core'
import {
WidgetIsReadyService,
WidgetIsReadySubject,
} from '@livechat/widget-angular'
@Component({
/* ... */
templateUrl: './app.component.html',
})
export class AppComponent implements OnInit {
widgetIsReady$: WidgetIsReadySubject
constructor(widgetIsReadyService: WidgetIsReadyService) {
this.widgetIsReady$ = widgetIsReadyService.subject
}
ngOnInit() {
this.widgetIsReady$.subscribe((widgetIsReady) => {
console.log('AppComponent.ngOnInit.widgetIsReady', widgetIsReady)
})
}
}<!-- app.component.html -->
<div>{{ widgetIsReady$ | async }}</div>Access the chatId and threadId of the chat if there's one currently available.
// app.component.ts
import { Component, OnInit } from '@angular/core'
import {
WidgetChatDataService,
WidgetChatDataSubject,
} from '@livechat/widget-angular'
@Component({
/* ... */
templateUrl: './app.component.html',
})
export class AppComponent implements OnInit {
chatData$: WidgetChatDataSubject
constructor(chatDataService: WidgetChatDataService) {
this.chatData$ = chatDataService.subject
}
ngOnInit() {
this.chatData$.subscribe((chatData) => {
console.log('AppComponent.ngOnInit.chatData', chatData)
})
}
}<!-- app.component.html -->
<div *ngIf="chatData$ | async as chatData">
<div>{{ chatData.availability }}</div>
<div>{{ chatData.visibility }}</div>
</div>Access the current greeting id and uniqueId if one is currently displayed (received and not hidden).
// app.component.ts
import { Component, OnInit } from '@angular/core'
import {
WidgetGreetingService,
WidgetGreetingSubject,
} from '@livechat/widget-angular'
@Component({
/* ... */
templateUrl: './app.component.html',
})
export class AppComponent implements OnInit {
greeting$: WidgetGreetingSubject
constructor(greetingService: WidgetGreetingService) {
this.greeting$ = greetingService.subject
}
ngOnInit() {
this.greeting$.subscribe((greeting) => {
console.log('AppComponent.ngOnInit.greeting', greeting)
})
}
}<!-- app.component.html -->
<div *ngIf="greeting$ | async as greeting">
<div>{{ greeting.availability }}</div>
<div>{{ greeting.visibility }}</div>
</div>Access the id, isReturning, status, and sessionVariables of the current customer if the chat widget is loaded.
// app.component.ts
import { Component, OnInit } from '@angular/core'
import {
WidgetCustomerDataService,
WidgetCustomerDataSubject,
} from '@livechat/widget-angular'
@Component({
/* ... */
templateUrl: './app.component.html',
})
export class AppComponent implements OnInit {
customerData$: WidgetCustomerDataSubject
constructor(customerDataService: WidgetCustomerDataService) {
this.customerData$ = customerDataService.subject
}
ngOnInit() {
this.customerData$.subscribe((customerData) => {
console.log('AppComponent.ngOnInit.customerData', customerData)
})
}
}<!-- app.component.html -->
<div *ngIf="customerData$ | async as customerData">
<div>{{ customerData.id }}</div>
<div>{{ customerData.isReturning }}</div>
<div>{{ customerData.status }}</div>
<ul>
<li *ngFor="let variable of customerData.sessionVariables | keyvalue">
{{ variable.value }}
</li>
</ul>
</div>In order to make Custom Identity Provider work, you'll have to properly implement and provide a set of following methods:
getToken- resolving Chat Widget token. If you want to cache the token, this should return the cached token instead of a fresh request to https://accounts.livechat.com/customer/token endpoint.getFreshToken- resolving Chat Widget token. This should always make a call for a fresh token from https://accounts.livechat.com/customer/token endpoint.hasToken- resolving boolean. It determines whether a token has been acquired.invalidate- resolving nothing. When called, it should remove the current token. There is no need to do anything else as a new token will be requested by getFreshToken afterwards.
// app.component.ts
import { Component } from '@angular/core'
import { EventHandlerPayload } from '@livechat/widget-angular'
@Component({
/* ... */
templateUrl: './app.component.html',
})
export class AppComponent {
customIdentityProvider() {
const baseAPI = 'YOUR_API_URL'
const userId = '30317220-c72d-11ed-2137-0242ac120002'
const getToken = async () => {
const response = await fetch(`${baseAPI}/getToken/${userId}`)
const token = await response.json()
console.log('getToken', token)
return token
}
const getFreshToken = async () => {
const response = await fetch(`${baseAPI}/getFreshToken/${userId}`)
const token = await response.json()
console.log('getFreshToken', token)
return token
}
const hasToken = async () => {
const response = await fetch(`${baseAPI}/hasToken/${userId}`)
const data = await response.json()
return data
}
const invalidateToken = async () => {
const response = await fetch(`${baseAPI}/invalidate/${userId}`)
const data = await response.json()
console.log(data)
}
return {
getToken,
getFreshToken,
hasToken,
invalidate: invalidateToken,
}
}
}<!-- app.component.html -->
<livechat-widget
license="12345678"
visibility="maximized"
[customIdentityProvider]="customIdentityProvider"
></livechat-widget>For more information about Custom Identity Provider, check out https://developers.livechat.com/docs/extending-chat-widget/custom-identity-provider
Pull requests are welcome. For major changes, please open an issue first, so we can discuss what you would like to change. Follow a Contributing guide for more details.
The code and documentation in this project are released under the MIT License.