1import type { AfterViewInit } from "@angular/core";
2import {
3  ChangeDetectionStrategy,
4  Component,
5  DestroyRef,
6  Injector,
7  ViewContainerRef,
8  inject,
9  input,
10  inputBinding,
11} from "@angular/core";
12import {
13  CopilotChat,
14  provideCopilotChatConfiguration,
15} from "@copilotkit/angular";
16
17import { agentIdForCurrentIntegration } from "../feature-agent";
18import { FeatureHeaderComponent } from "./feature-header.component";
19import {
20  createDynamicComponent,
21  renderDynamicComponent,
22} from "./render-dynamic-component";
23
24interface SlotMessage {
25  id: string;
26  role: "assistant";
27  content?: string;
28}
29
30@Component({
31  selector: "showcase-custom-assistant-message",
32  changeDetection: ChangeDetectionStrategy.OnPush,
33  host: {
34    class: "custom-assistant-message",
35    "data-testid": "custom-assistant-message",
36    "data-slot-label": "MessageView.AssistantMessage",
37    "data-message-role": "assistant",
38  },
39  template: `
40    <p class="feature-eyebrow">Custom Angular assistant slot</p>
41    <div>{{ message().content }}</div>
42  `,
43})
44export class CustomAssistantMessageComponent {
45  readonly message = input.required<SlotMessage>();
46}
47
48@Component({
49  selector: "showcase-chat-slots-feature",
50  imports: [FeatureHeaderComponent],
51  changeDetection: ChangeDetectionStrategy.OnPush,
52  host: { class: "feature-page" },
53  template: `
54    <showcase-feature-header />
55    <main class="chat-surface" aria-label="Customized CopilotKit chat">
56      <ng-container #chatHost />
57    </main>
58  `,
59})
60export class ChatSlotsFeatureComponent implements AfterViewInit {
61  private readonly chatHost = inject(ViewContainerRef);
62  private readonly injector = inject(Injector);
63  private readonly destroyRef = inject(DestroyRef);
64
65  ngAfterViewInit(): void {
66    const agentId = agentIdForCurrentIntegration("chat-slots");
67    const childInjector = Injector.create({
68      parent: this.injector,
69      providers: [...provideCopilotChatConfiguration({ agentId })],
70    });
71    this.destroyRef.onDestroy(() => childInjector.destroy());
72    const chat = createDynamicComponent(this.chatHost, CopilotChat, {
73      injector: childInjector,
74      bindings: [
75        inputBinding("agentId", () => agentId),
76        inputBinding(
77          "assistantMessageComponent",
78          () => CustomAssistantMessageComponent,
79        ),
80      ],
81    });
82    renderDynamicComponent(chat);
83  }
84}
85
b203d8f70
CopilotKit Showcase