Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
cometchat avatar

Cometchat Angular Customization

  • 4 installs
  • 70 repo stars
  • Updated June 23, 2026
  • cometchat/cometchat-skills

Customizes the CometChat Angular UI Kit without forking via a four-tier model: Angular inputs, request builders, text formatters and message templates, then DataSource decorators and the event bus.

About

This skill teaches how to change the Angular UI Kit's behavior or appearance without modifying the kit, using a four-tier model from Angular inputs up to DataSource decorators and events. A developer uses it to filter data, reformat text, or override message rendering.

  • Four-tier model from Angular inputs to DataSource decorators
  • Request builders, text formatters, message templates, and event bus

Cometchat Angular Customization by the numbers

  • 4 all-time installs (skills.sh)
  • Ranked #1,817 of 2,245 Frontend Development skills by installs in the Skillselion catalog
  • Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/cometchat/cometchat-skills --skill cometchat-angular-customization

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs4
repo stars70
Last updatedJune 23, 2026
Repositorycometchat/cometchat-skills

What it does

Customizes the CometChat Angular UI Kit without forking via a four-tier model: Angular inputs, request builders, text formatters and message templates, then DataSource decorators and the event bus.

Files

SKILL.mdMarkdownGitHub ↗

Purpose

Teaches Claude how to change the behavior or appearance of the Angular UI Kit without modifying the kit itself. Four tiers, from cheapest to deepest:

Tier 1 — Angular inputs     (95% of asks solved here)
Tier 2 — RequestBuilder     (filter what data loads)
Tier 3 — Formatters + Templates   (change how text / messages render)
Tier 4 — DataSource decorators + Events  (last resort, powerful)

Always try Tier 1 first. Escalate only when the tier can't do what the user wants.

Read `cometchat-angular-components` first — the catalog is the source of truth for input names, slot templates, and event names that this skill builds on.

Ground truth: docs/ui-kit/angular/custom-text-formatter-guide, docs/ui-kit/angular/events, docs/ui-kit/angular/methods, and the kit's source.

---

Four-tier triage — pick the right tier before writing any code

Start with Tier 1 every time. The Angular UI Kit follows a "inputs over components" philosophy — most additions are inputs on already-mounted components, not new components or custom code.

Quick task → input lookup

Before escalating to any tier, check if an existing component input already does what you need:

User asks forLikely input on which component
Search bar[hideSearch]="false" on <cometchat-conversations>, <cometchat-users>, <cometchat-groups>
Filter conversations[conversationsRequestBuilder] on <cometchat-conversations>
Filter messages[messagesRequestBuilder] on <cometchat-message-list>
Filter users / groups[usersRequestBuilder] / [groupsRequestBuilder]
Custom empty state[emptyStateView] on list components
Custom error UI[errorStateView]
Custom loading UI[loadingStateView]
Custom list item[listItemView] on <cometchat-conversations>, <cometchat-users>, <cometchat-groups>
Custom header subtitle[subtitleView] on <cometchat-message-header>
Custom header menu[menu] on <cometchat-message-header>
Hide receipts[hideReceipt]="true" on <cometchat-message-list>
Disable reactions[disableReactions]="true" on <cometchat-message-list>
Disable mentions[disableMentions]="true" on <cometchat-message-composer>
Custom send button[sendButtonView] on <cometchat-message-composer>
Custom attachment options[attachmentOptions] on <cometchat-message-composer>
Click handler on conversation[onItemClick] on <cometchat-conversations>
Active conversation highlight[activeConversation] on <cometchat-conversations>
Note: [hideReactions], [hideReplyInThreadOption], [hideEditMessageOption], [hideDeleteMessageOption], [hideTranslateMessageOption] do not exist in the Angular v4 UIKit. Use [disableReactions] for reactions. Message action options are controlled via the [options] callback or [templates] prop.

If a matching input exists, add the input and stop. No new components, no custom CSS, no new files.

If they want to...Use TierCost
Hide a feature (thread option, receipts, edit, etc.)Tier 1 — [hide*] inputs1 line of HTML
Customize a subsection (header subtitle, list item, empty state)Tier 1 — [*View] / [*Template] slot1 ng-template
Filter what loads (only show online users, exclude blocked, include tags)Tier 2 — [*RequestBuilder]1 builder
Change how URLs / mentions / hashtags / emojis render inlineTier 3 — [textFormatters]Subclass of CometChatTextFormatter
Render a custom message type (custom bubble, custom interactive msg)Tier 3 — [templates] + CometChatMessageTemplate1 template + 1 component
React to events from another componentTier 4 — CometChatConversationEvents / CometChatMessageEventsRxJS subscription
Rewrite how data flows through the kitTier 4 — DataSourceDecoratorClass extension

If a user's ask fits Tier 1 but you jumped to Tier 3, you've written 50 lines that a 1-line input could have replaced. Start low.

---

Tier 1 — Angular inputs (hide / slot views / styles)

1a. [hide*] inputs

Turn features off with a single input binding:

<cometchat-message-list
  [user]="selectedUser"
  [hideReceipt]="true"
  [disableReactions]="false"
  [disableSoundForMessages]="false"
></cometchat-message-list>

Real hide/disable inputs on <cometchat-message-list>: [hideReceipt], [hideError], [hideDateSeparator], [disableReactions], [disableSoundForMessages], [disableMentions].

Full list of inputs per component: cometchat-angular-components. Check there before writing custom code.

1b. ng-template slot views — replace a section

Every component has slot inputs for replacing named sections of its default UI. Pass an ng-template reference:

<cometchat-conversations
  [listItemView]="customListItem"
></cometchat-conversations>

<ng-template #customListItem let-conversation>
  <div class="custom-item">
    <span class="name">{{ conversation.getConversationWith().getName() }}</span>
    <span class="time">{{ conversation.getLastMessage()?.getSentAt() | date:'shortTime' }}</span>
  </div>
</ng-template>
import { ViewChild, TemplateRef } from "@angular/core";

@Component({ /* ... */ })
export class AppComponent {
  @ViewChild("customListItem") customListItem!: TemplateRef<any>;
}

For the message header's subtitle:

<cometchat-message-header
  [user]="selectedUser"
  [subtitleView]="customSubtitle"
></cometchat-message-header>

<ng-template #customSubtitle let-user>
  <span style="color: #09C26F; font-size: 12px;">
    {{ user?.getStatus() === 'online' ? 'Online' : 'Offline' }}
  </span>
</ng-template>

1c. [*Style] inputs — per-component styling

See cometchat-angular-theming § 4 for the full style object reference. Use [*Style] for one-off overrides on a single component instance.

---

Tier 2 — RequestBuilder filtering

For "I want to show a subset of X", use the matching [*RequestBuilder]. Never post-filter in-render.

import { CometChat } from "@cometchat/chat-sdk-javascript";

// Only conversations in a specific tag group
conversationsRequestBuilder = new CometChat.ConversationsRequestBuilder()
  .setLimit(20)
  .setUserTags(["premium"])
  .setConversationType(CometChat.RECEIVER_TYPE.USER);

// Only online users, exclude blocked
usersRequestBuilder = new CometChat.UsersRequestBuilder()
  .setLimit(30)
  .setStatus("online")
  .hideBlockedUsers(true);

// Only groups you've joined
groupsRequestBuilder = new CometChat.GroupsRequestBuilder()
  .setLimit(30)
  .joinedOnly(true);

// Message list — exclude system messages
messagesRequestBuilder = new CometChat.MessagesRequestBuilder()
  .setUID(this.selectedUser.getUid())
  .setLimit(30)
  .setCategories(["message"]);

---

Tier 3 — Text formatters + message templates

3a. Custom text formatter — inline text patterns

CometChatTextFormatter is an abstract base class for matching inline text patterns and replacing them with custom HTML.

// hashtag-formatter.ts
import { CometChatTextFormatter } from "@cometchat/uikit-shared";

export class HashtagFormatter extends CometChatTextFormatter {
  constructor() {
    super();
    this.setTrackingCharacter("#");
    this.setRegexPatterns([/\B#(\w+)\b/g]);
    this.setRegexToReplaceFormatting([/#(\w+)/g]);
  }

  override getFormattedText(inputText: string): string {
    if (!inputText) return "";
    return inputText.replace(
      /\B#(\w+)\b/g,
      '<span style="color: #6851D6; font-weight: 600;">#$1</span>'
    );
  }

  override getOriginalText(inputText: string): string {
    if (!inputText) return "";
    return inputText.replace(/<span[^>]*>(#\w+)<\/span>/g, "$1");
  }
}

Register by passing to both <cometchat-message-list> and <cometchat-message-composer>:

// In your component:
import { HashtagFormatter } from "./hashtag-formatter";
import { CometChatMentionsFormatter, CometChatUrlsFormatter } from "@cometchat/uikit-shared";

textFormatters = [
  new CometChatMentionsFormatter(),
  new CometChatUrlsFormatter([
    /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&/=]*)/gi,
  ]),
  new HashtagFormatter(),
];
<cometchat-message-list
  [user]="selectedUser"
  [textFormatters]="textFormatters"
></cometchat-message-list>
<cometchat-message-composer
  [user]="selectedUser"
  [textFormatters]="textFormatters"
></cometchat-message-composer>

⚠️ Pass the same `textFormatters` array to both list and composer. If they differ, messages look different when sent vs. received.

3b. Custom message template — entire custom bubble

For rendering a totally custom message type, use CometChatMessageTemplate.

// In your component:
import { CometChatMessageTemplate } from "@cometchat/uikit-shared";
import { ChatConfigurator } from "@cometchat/chat-uikit-angular";

// Get default templates to merge with
const defaultTemplates = ChatConfigurator.getDataSource().getAllMessageTemplates();

// Create a custom template for a "poll" message type
const pollTemplate = new CometChatMessageTemplate({
  type: "poll",
  category: "custom",
  ContentView: (message: CometChat.BaseMessage, alignment: string) => {
    // Return an Angular component reference or HTML string
    // For Angular, use a ViewContainerRef approach or pass a component factory
    return null; // implement with your Angular component
  },
});

messageTemplates = [pollTemplate, ...defaultTemplates];
<cometchat-message-list
  [user]="selectedUser"
  [templates]="messageTemplates"
></cometchat-message-list>

---

Tier 4 — Event bus + DataSource decorators

4a. Event bus — RxJS subscriptions

Subscribe to events that UI Kit components emit so your own code can react.

import { Component, OnInit, OnDestroy } from "@angular/core";
import { Subscription } from "rxjs";
import {
  CometChatMessageEvents,
  CometChatConversationEvents,
  CometChatGroupEvents,
} from "@cometchat/chat-uikit-angular";
import { CometChat } from "@cometchat/chat-sdk-javascript";

@Component({ /* ... */ })
export class AppComponent implements OnInit, OnDestroy {
  private subscriptions: Subscription[] = [];

  ngOnInit(): void {
    this.subscriptions.push(
      CometChatMessageEvents.ccMessageSent.subscribe(
        ({ message, status }: { message: CometChat.BaseMessage; status: string }) => {
          if (status === "sent") {
            // analytics.track("message_sent", { id: message.getId() });
          }
        }
      ),
      CometChatConversationEvents.ccConversationDeleted.subscribe(
        (conversation: CometChat.Conversation) => {
          // Remove from local cache
        }
      ),
      CometChatGroupEvents.ccGroupLeft.subscribe(
        ({ userLeft, leftGroup }: any) => {
          // Handle group leave
        }
      )
    );
  }

  ngOnDestroy(): void {
    this.subscriptions.forEach((sub) => sub.unsubscribe());
  }
}

Always unsubscribe in `ngOnDestroy`. Angular components are destroyed on navigation — leaked subscriptions cause duplicate event handling.

Available event streams

Event classKey events
CometChatMessageEventsccMessageSent, ccMessageEdited, ccMessageDeleted, ccMessageRead, ccLiveReaction
CometChatConversationEventsccConversationDeleted, ccUpdateConversation
CometChatGroupEventsccGroupCreated, ccGroupDeleted, ccGroupLeft, ccGroupMemberScopeChanged, ccGroupMemberKicked, ccGroupMemberBanned, ccGroupMemberJoined, ccGroupMemberAdded, ccOwnershipChanged
CometChatUserEventsccUserBlocked, ccUserUnblocked

4b. DataSource decorators

DataSourceDecorator wraps the kit's internal data source to override specific methods without forking the whole kit.

import {
  DataSource,
  DataSourceDecorator,
  ChatConfigurator,
} from "@cometchat/chat-uikit-angular";

class MyDataSource extends DataSourceDecorator {
  constructor(source: DataSource) {
    super(source);
  }

  // Override only the method you want to change
  override getConversationsRequestBuilder() {
    const builder = super.getConversationsRequestBuilder();
    builder.setUserAndGroupTags(true);
    return builder;
  }
}

// Register before init — wraps the default data source
ChatConfigurator.dataSource = new MyDataSource(ChatConfigurator.getDataSource());
// Then call CometChatUIKit.init(settings)

This is an escape hatch, not a first tool. Re-check whether Tier 1 (inputs) or Tier 3 (templates) could have solved it before reaching for Tier 4.

---

5. Recipes (common customization asks → right tier)

"Filter the conversation list to just premium users"

Tier 2[conversationsRequestBuilder] with .setUserTags(["premium"]).

"Custom empty state for the users list"

Tier 1[emptyStateView] slot input on <cometchat-users>.

"Custom list item for conversations"

Tier 1[listItemView] slot input on <cometchat-conversations>.

"Show a custom view when the user types @"

Tier 3a — subclass CometChatMentionsFormatter, implement search(key) with your own suggestion source.

"When a message is sent, log it to our analytics"

Tier 4aCometChatMessageEvents.ccMessageSent.subscribe(...).

"When a group is deleted, navigate away"

Tier 4aCometChatGroupEvents.ccGroupDeleted.subscribe(...).

"Render custom avatars for all users based on their department"

Tier 1[listItemView] slot on <cometchat-conversations> + <cometchat-users>.

"Disable the file attachment option"

Tier 1 — filter the [attachmentOptions] input on <cometchat-message-composer>.

"Custom message type: a 'ping' message"

Tier 3b — create a CometChatMessageTemplate with category: "custom" + type: "ping", render a custom Angular component, send via CometChat.sendCustomMessage.

---

6. Anti-patterns

1. Don't hand-roll a bubble when a template will do. CometChatMessageTemplate (Tier 3b) gives you full control over rendering + options without losing theming, reactions, typing, receipts.

2. Don't post-filter a list's data after render. If you want "only online users," use Tier 2 usersRequestBuilder.setStatus("online") — don't fetch everyone then hide rows with *ngIf.

3. Don't forget to unsubscribe in `ngOnDestroy`. Angular components are destroyed on navigation; leaked subscriptions cause duplicate event handling.

4. Don't put `CometChatTextFormatter` instances in component state that gets recreated. Construct them once at class level (as a property, not in ngOnInit); re-creating them on every change detection cycle loses the internal suggestion state.

5. Don't fork or patch `@cometchat/chat-uikit-angular` directly. Every customization should be possible via Tiers 1-4. Forking breaks on kit upgrades.

6. Don't reach for Tier 4 before trying 1-3. DataSource decorators are powerful but fragile to kit internal changes. Inputs, request builders, and templates are stable surface area.

---

Skill routing reference

SkillWhen to route
cometchat-angular-coreInit / login / module setup
cometchat-angular-componentsInput reference — which [hide*], [*View], [*RequestBuilder] is available
cometchat-angular-placementWhere to put the customized components
cometchat-angular-themingApp-wide color / typography — Tier 1 alternative to [*Style]
cometchat-angular-featuresWhich out-of-the-box features exist
cometchat-angular-customizationThis skill — four-tier triage + custom formatters / templates / DataSource / events
cometchat-angular-productionWhen customization depends on production auth
cometchat-angular-troubleshootingFormatter doesn't apply, listener fires twice, slot view renders nothing

Related skills

Frontend Developmentfrontendintegrations

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.