All Components

Using with Microsoft Bot Framework

The Chat provides integration options for connecting the component to chat bots which are built with Microsoft Bot Framework.

Travel Agent Chat Bot

The following example demonstrates how to connect the Chat to chat bots which run on Azure Bot Service and use the Direct Line protocol to create a Travel Agent Chat Bot.

import { Component, ViewEncapsulation } from '@angular/core';

import { Subject } from 'rxjs/Subject';
import { Observable } from 'rxjs/Observable';
import { scan } from 'rxjs/operators/scan';
import { merge } from 'rxjs/observable/merge';

import { Message, User, Action, ExecuteActionEvent, SendMessageEvent } from '@progress/kendo-angular-conversational-ui';
import { Agent } from './agent';

// API secret
const secret = 'Y_ly-If6haE.cwA.PQE.ZwOOsq4MlHcD3_YLFI-t9oW6L6DXMMBoi67LBz9WaWA';

@Component({
  encapsulation: ViewEncapsulation.None,
  selector: 'my-app',
  styles: [`
    .k-card-image {
      max-width: 250px;
    }
  `],
  template: `
      <kendo-chat
        [messages]="feed | async"
        [user]="user"
        (sendMessage)="sendMessage($event)"
      >
        <ng-template kendoChatAttachmentTemplate let-att>
          <ng-container [ngSwitch]="att.contentType">
            <kendo-chat-hero-card *ngSwitchCase="'application/vnd.microsoft.card.hero'"
              imageUrl="{{ att.content.images ? att.content.images[0]?.url : '' }}"
              [title]="att.content.title || att.content.text"
              [subtitle]="att.content.subtitle"
              [actions]="att.content.buttons"
              (executeAction)="heroAction($event)"
            >
            </kendo-chat-hero-card>

            <adaptive-card [data]="att.content" *ngSwitchCase="'application/vnd.microsoft.card.adaptive'">
            </adaptive-card>

            <div class="k-card" *ngSwitchDefault>
              {{ att.content | json }}
            </div>
          </ng-container>
        </ng-template>
      </kendo-chat>
    `
})
export class AppComponent {
  public feed: Observable<Message[]>;

  public readonly user: User = {
    id: 'User'
  };

  public readonly bot: User = {
    id: 'Botyo-BotTesting',
    name: 'Travel Agent',
    avatarUrl: 'https://demos.telerik.com/kendo-ui/content/chat/VacationBot.png'
  };

  private agent: Agent = new Agent(this.bot, secret);
  private local: Subject<Message> = new Subject<Message>();

  constructor() {
    // Merge local and remote messages into a single stream
    this.feed = merge(
      this.local,
      this.agent.responses
    ).pipe(
      // ... and emit an array of all messages
      scan((acc, x) => [...acc, x], [])
    );
  }

  public sendMessage(e: SendMessageEvent): void {
    this.send(e.message);
  }

  public heroAction(button: Action) {
    if (button.type === 'imBack') {
      const message = {
        author: this.user,
        text: button.value
      };

      this.send(message);
    }
  }

  private send(message: Message) {
    this.local.next(message);
    this.local.next({
      author: this.bot,
      typing: true
    });

    this.agent.submit(message);
  }
}
import { Component, Input, ElementRef, HostBinding, ViewChild } from '@angular/core';
import { AdaptiveCard, HostConfig } from 'adaptivecards';

@Component({
  selector: 'adaptive-card',
  template: `
    <div #body class='k-card-body'>
    </div>
  `
})
export class AdaptiveCardComponent {
  @Input()
  public set data(data: any) {
    this.cardData = data;
    this.card.parse(data);

    if (this.body) {
      const content = this.card.render();
      this.body.nativeElement.append(content);
    }
  }

  public get data(): any {
    return this.cardData;
  }

  @HostBinding('class.k-card')
  public cssClass = true;

  @ViewChild('body')
  public body: ElementRef;

  private cardData: any;
  private card: AdaptiveCards = new AdaptiveCard();

  constructor() {
    this.card.hostConfig = new HostConfig({
      fontFamily: 'Segoe UI, Helvetica Neue, sans-serif'
    });
  }
}
import { Subject } from 'rxjs/Subject';

import { from } from 'rxjs/observable/from';
import { DirectLine } from 'botframework-directlinejs';
import { Action, Message, User } from '@progress/kendo-angular-conversational-ui';

export class Agent {
  public readonly responses: Subject<Message> = new Subject<Message>();
  private client: DirectLine;

  constructor(private user: User, secret: string) {
    this.client = new DirectLine({ secret });

    this.client.activity$.subscribe(data => this.onResponse(data));
  }

  public submit(msg: Message): void {
    const req = this.client.postActivity({
      type: 'message',
      from: { id: msg.author.id },
      text: msg.text
    });

    req.subscribe(data => this.onResponse(data));
  }

  private onResponse(response: any): void {
    if (!response.from || response.from.id !== this.user.id) {
      return;
    }

    const timestamp = new Date(response.timestamp);
    const message = {
      attachments: response.attachments,
      author: this.user,
      suggestedActions: this.mapActions(response.suggestedActions),
      text: response.text,
      timestamp,
      typing: response.type === 'typing'
    };

    this.responses.next(message);
  }

  private mapActions(data: any): Action {
    if (!data || !data.actions) {
      return [];
    }

    return data.actions.map(action => ({
      type: action.type === 'imBack' ? 'reply' : action.type,
      title: action.title,
      value: action.value
    }));
  }
}
import { NgModule } from '@angular/core';
import { Component } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { ChatModule } from '@progress/kendo-angular-conversational-ui';

import { AppComponent } from './app.component';
import { AdaptiveCardComponent } from './adaptive-card.component';

@NgModule({
  imports:      [
    BrowserModule,
    BrowserAnimationsModule,
    ChatModule
  ],
  declarations: [
    AppComponent,
    AdaptiveCardComponent
  ],
  bootstrap:    [ AppComponent ]
})

export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';

const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule);

Health Care Chat Bot

The following example demonstrates how to connect the Chat to chat bots which run on Azure Bot Service and use the Direct Line protocol to create a Health Care Chat Bot.

import { Component, ViewEncapsulation } from '@angular/core';

import { Subject } from 'rxjs/Subject';
import { Observable } from 'rxjs/Observable';
import { scan } from 'rxjs/operators/scan';
import { merge } from 'rxjs/observable/merge';

import { Message, User, Action, ExecuteActionEvent, SendMessageEvent } from '@progress/kendo-angular-conversational-ui';
import { Agent } from './agent';

// API secret
const secret = 'yFLWlpeK3CI.cwA.r18.M9VxoEcUnMthu5zsWX2Ox95r5YCcvbC_GvPJooRM0sQ';

@Component({
  encapsulation: ViewEncapsulation.None,
  selector: 'my-app',
  styles: [`
    .k-card-image {
      max-width: 250px;
    }
  `],
  template: `
      <kendo-chat
        [messages]="feed | async"
        [user]="user"
        (sendMessage)="sendMessage($event)"
      >
        <ng-template kendoChatAttachmentTemplate let-att>
          <ng-container [ngSwitch]="att.contentType">
            <kendo-chat-hero-card *ngSwitchCase="'application/vnd.microsoft.card.hero'"
              imageUrl="{{ att.content.images ? att.content.images[0]?.url : '' }}"
              [title]="att.content.title || att.content.text"
              [subtitle]="att.content.subtitle"
              [actions]="att.content.buttons"
              (executeAction)="heroAction($event)"
            >
            </kendo-chat-hero-card>

            <adaptive-card [data]="att.content" *ngSwitchCase="'application/vnd.microsoft.card.adaptive'">
            </adaptive-card>

            <div class="k-card" *ngSwitchDefault>
              {{ att.content }}
            </div>
          </ng-container>
        </ng-template>
      </kendo-chat>
    `
})
export class AppComponent {
  public feed: Observable<Message[]>;

  public readonly user: User = {
    id: 'User'
  };

  public readonly bot: User = {
    id: 'HealthCareBotService',
    name: 'HealthCare Bot',
    avatarUrl: 'https://demos.telerik.com/kendo-ui/content/chat/HealthCareBot.png'
  };

  private agent: Agent = new Agent(this.bot, secret);
  private local: Subject<Message> = new Subject<Message>();

  constructor() {
    // Merge local and remote messages into a single stream
    this.feed = merge(
      this.local,
      this.agent.responses
    ).pipe(
      // ... and emit an array of all messages
      scan((acc, x) => [...acc, x], [])
    );
  }

  public sendMessage(e: SendMessageEvent): void {
    this.send(e.message);
  }

  public heroAction(button: Action) {
    if (button.type === 'imBack') {
      const message = {
        author: this.user,
        text: button.value
      };

      this.send(message);
    }
  }

  private send(message: Message) {
    this.local.next(message);
    this.local.next({
      author: this.bot,
      typing: true
    });

    this.agent.submit(message);
  }
}
import { Component, Input, ElementRef, HostBinding, ViewChild } from '@angular/core';
import { AdaptiveCard, HostConfig } from 'adaptivecards';

@Component({
  selector: 'adaptive-card',
  template: `
    <div #body class='k-card-body'>
    </div>
  `
})
export class AdaptiveCardComponent {
  @Input()
  public set data(data: any) {
    this.cardData = data;
    this.card.parse(data);

    if (this.body) {
      const content = this.card.render();
      this.body.nativeElement.append(content);
    }
  }

  public get data(): any {
    return this.cardData;
  }

  @HostBinding('class.k-card')
  public cssClass = true;

  @ViewChild('body')
  public body: ElementRef;

  private cardData: any;
  private card: AdaptiveCards = new AdaptiveCard();

  constructor() {
    this.card.hostConfig = new HostConfig({
      fontFamily: 'Segoe UI, Helvetica Neue, sans-serif'
    });
  }
}
import { Subject } from 'rxjs/Subject';

import { from } from 'rxjs/observable/from';
import { DirectLine } from 'botframework-directlinejs';
import { Action, Message, User } from '@progress/kendo-angular-conversational-ui';

export class Agent {
  public readonly responses: Subject<Message> = new Subject<Message>();
  private client: DirectLine;

  constructor(private user: User, secret: string) {
    this.client = new DirectLine({ secret });

    this.client.activity$.subscribe(data => this.onResponse(data));
  }

  public submit(msg: Message): void {
    const req = this.client.postActivity({
      type: 'message',
      from: { id: msg.author.id },
      text: msg.text
    });

    req.subscribe(data => this.onResponse(data));
  }

  private onResponse(response: any): void {
    if (!response.from || response.from.id !== this.user.id) {
      return;
    }

    const timestamp = new Date(response.timestamp);
    const message = {
      attachments: response.attachments,
      author: this.user,
      suggestedActions: this.mapActions(response.suggestedActions),
      text: response.text,
      timestamp,
      typing: response.type === 'typing'
    };

    this.responses.next(message);
  }

  private mapActions(data: any): Action {
    if (!data || !data.actions) {
      return [];
    }

    return data.actions.map(action => ({
      type: action.type === 'imBack' ? 'reply' : action.type,
      title: action.title,
      value: action.value
    }));
  }
}
import { NgModule } from '@angular/core';
import { Component } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { ChatModule } from '@progress/kendo-angular-conversational-ui';

import { AppComponent } from './app.component';
import { AdaptiveCardComponent } from './adaptive-card.component';

@NgModule({
  imports:      [
    BrowserModule,
    BrowserAnimationsModule,
    ChatModule
  ],
  declarations: [
    AppComponent,
    AdaptiveCardComponent
  ],
  bootstrap:    [ AppComponent ]
})

export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';

const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule);
In this article