Skip to main content
MessageBubbleConfigService is the centralized Angular service for configuring how message bubbles are rendered across the CometChat Angular UIKit. It lets you customize individual sections of any message bubble — globally or per message type — without touching component templates. The service is providedIn: 'root' (singleton by default). All cometchat-message-list instances share the same configuration unless you scope the service.

Import

import { MessageBubbleConfigService, BubblePart, BubblePartMap, MessageTypeKey } from '@cometchat/chat-uikit-angular';

Priority Logic

When the message bubble resolves a view for a given message type and part, it follows this order:
  1. Component @Input template (passed directly to cometchat-message-bubble)
  2. Type-specific service view (setBubbleView())
  3. Global service view (setGlobalView() / setGlobalViews())
  4. Default rendering

Types

BubblePart

The sections of a message bubble that can be customized:
ValueDescription
bubbleViewThe entire bubble wrapper
contentViewMain message content area
bottomViewArea below content (e.g., reactions)
footerViewFooter area of the bubble
leadingViewLeading area (e.g., avatar for incoming messages)
headerViewHeader area (e.g., sender name)
statusInfoViewStatus info area (e.g., timestamp, receipts)
replyViewReply preview area for quoted messages
threadViewThread indicator area for messages with replies

MessageTypeKey

A string in the format {type}_{category}. Standard keys:
KeyDescription
text_messageText messages
image_messageImage messages
video_messageVideo messages
audio_messageAudio messages
file_messageFile messages
delete_actionDeleted messages
groupMember_actionGroup member action messages
audio_callAudio call messages
video_callVideo call messages
extension_poll_customPoll messages
extension_sticker_customSticker messages
extension_document_customDocument messages
extension_whiteboard_customWhiteboard messages
meeting_customMeeting messages
For custom message types, use {yourType}_custom (e.g., location_custom).

BubblePartMap

interface BubblePartMap {
  bubbleView?: TemplateRef<any> | null;
  contentView?: TemplateRef<any> | null;
  bottomView?: TemplateRef<any> | null;
  footerView?: TemplateRef<any> | null;
  leadingView?: TemplateRef<any> | null;
  headerView?: TemplateRef<any> | null;
  statusInfoView?: TemplateRef<any> | null;
  replyView?: TemplateRef<any> | null;
  threadView?: TemplateRef<any> | null;
}

Methods

setBubbleView

Sets a custom view for one or more bubble parts for a specific message type. Merges with any existing configuration for that type.
setBubbleView(messageType: MessageTypeKey, partMap: BubblePartMap): void
this.bubbleConfig.setBubbleView('text_message', {
  contentView: this.customTextContent,
  footerView: this.customFooter,
});

setGlobalView

Sets a single global view that applies to all message types as a fallback.
setGlobalView(part: BubblePart, view: TemplateRef<any> | null): void
// Apply a custom status info view to every message type
this.bubbleConfig.setGlobalView('statusInfoView', this.customStatusInfo);

// Clear a global view
this.bubbleConfig.setGlobalView('footerView', null);

setGlobalViews

Sets multiple global views at once. Merges with existing global configuration.
setGlobalViews(partMap: BubblePartMap): void
this.bubbleConfig.setGlobalViews({
  footerView: this.customFooter,
  statusInfoView: this.customStatusInfo,
  leadingView: this.customAvatar,
});

setMessageTemplates

Batch-configures multiple message types in a single call.
setMessageTemplates(templates: Record<MessageTypeKey, BubblePartMap>): void
this.bubbleConfig.setMessageTemplates({
  text_message: { contentView: this.textContent },
  image_message: { contentView: this.imageContent, headerView: this.imageHeader },
  video_message: { contentView: this.videoContent },
});

getView

Retrieves the resolved view for a message type and bubble part, applying the priority chain.
getView(messageType: MessageTypeKey, part: BubblePart): TemplateRef<any> | null
Returns null if no view is configured (component uses default rendering).

clearAll

Clears all type-specific and global configurations, resetting to default rendering.
clearAll(): void

clearType

Clears configuration for a specific message type. Global views and other types are unaffected.
clearType(messageType: MessageTypeKey): void

clearGlobalViews

Clears all global views. Type-specific configurations are unaffected.
clearGlobalViews(): void

Reactive Properties

PropertyTypeDescription
configVersionSignal<number>Increments on every configuration change. Read in templates to trigger re-renders.
configChanged$Subject<void>Emits on every configuration change. Subscribe in OnPush components to call markForCheck().

Usage Examples

Customize a Specific Message Type

import { Component, ViewChild, TemplateRef, AfterViewInit, inject } from '@angular/core';
import { MessageBubbleConfigService } from '@cometchat/chat-uikit-angular';

@Component({
  standalone: true,
  template: `
    <ng-template #customTextContent let-context>
      <div class="my-text-bubble">{{ context.message.getText() }}</div>
    </ng-template>

    <cometchat-message-list [user]="user"></cometchat-message-list>
  `
})
export class ChatComponent implements AfterViewInit {
  @ViewChild('customTextContent') customTextContent!: TemplateRef<any>;
  private bubbleConfig = inject(MessageBubbleConfigService);

  ngAfterViewInit(): void {
    this.bubbleConfig.setBubbleView('text_message', {
      contentView: this.customTextContent,
    });
  }
}

Apply a Global View to All Message Types

@Component({
  standalone: true,
  template: `
    <ng-template #customStatus let-context>
      <span class="my-status">{{ context.message.getSentAt() | date:'shortTime' }}</span>
    </ng-template>

    <cometchat-message-list [user]="user"></cometchat-message-list>
  `
})
export class ChatComponent implements AfterViewInit {
  @ViewChild('customStatus') customStatus!: TemplateRef<any>;
  private bubbleConfig = inject(MessageBubbleConfigService);

  ngAfterViewInit(): void {
    // Applies to every message type
    this.bubbleConfig.setGlobalView('statusInfoView', this.customStatus);
  }
}

Batch Configure Multiple Types

ngAfterViewInit(): void {
  this.bubbleConfig.setMessageTemplates({
    text_message: { contentView: this.textContent },
    image_message: { contentView: this.imageContent },
    audio_message: { contentView: this.audioContent },
  });
}

React to Configuration Changes (OnPush)

import { ChangeDetectorRef, inject } from '@angular/core';
import { MessageBubbleConfigService } from '@cometchat/chat-uikit-angular';

export class MyOnPushComponent {
  private bubbleConfig = inject(MessageBubbleConfigService);
  private cdr = inject(ChangeDetectorRef);

  ngOnInit(): void {
    this.bubbleConfig.configChanged$.subscribe(() => {
      this.cdr.markForCheck();
    });
  }
}

Scoping for Multiple Instances

By default, MessageBubbleConfigService is a root-level singleton — all message lists share the same configuration. To give a specific component subtree its own independent configuration (e.g., a thread panel with different bubble styles), provide the service at the wrapper component level:
import { Component, inject } from '@angular/core';
import { CometChatMessageListComponent, MessageBubbleConfigService } from '@cometchat/chat-uikit-angular';

@Component({
  selector: 'app-thread-panel',
  standalone: true,
  imports: [CometChatMessageListComponent],
  providers: [MessageBubbleConfigService], // Creates a new instance for this subtree
  template: `<cometchat-message-list [user]="user" [parentMessageId]="parentMessageId"></cometchat-message-list>`
})
export class ThreadPanelComponent {
  // Injects the LOCAL instance, not the root singleton
  private bubbleConfig = inject(MessageBubbleConfigService);

  ngAfterViewInit(): void {
    this.bubbleConfig.setBubbleView('text_message', {
      contentView: this.threadTextTemplate,
    });
  }
}
The main chat panel continues to use the root singleton, unaffected by the thread panel’s configuration.
Each cometchat-message-list provides its own MessageListService internally. The scoping technique above applies only to customization services like MessageBubbleConfigService and FormatterConfigService.

See Also