Overview
The CometChatUsers component displays a real-time, scrollable list of users with support for search, selection modes, and extensive customization. It provides an integral search functionality, allowing you to locate any specific user swiftly and easily. For each user listed, the component displays the user’s name by default, in conjunction with their avatar when available. Furthermore, it includes a status indicator, visually informing you whether a user is currently online or offline.
The component follows a Manager-based Architecture where:
UsersManager handles SDK request building and pagination
Component manages state, real-time listeners, and UI rendering
Templates allow extensive customization of all UI sections
Key Features
Real-time Updates : Automatic updates for user online/offline status changes
Flexible Customization : Extensive template projection for all UI sections
Selection Modes : Support for single and multiple user selection with shift-click range selection
Selected Users Preview : Display chips for selected users in multiple selection mode
Alphabetical Section Headers : Group users by first letter of name
Search Functionality : Built-in search with 300ms debouncing
Keyboard Navigation : Full keyboard accessibility with arrow keys and shortcuts (WCAG 2.1 Level AA compliant)
Context Menu : Customizable actions for each user
Error Handling : Comprehensive error handling with custom error views
Keyboard Accessibility
CometChatUsers is fully keyboard accessible and meets WCAG 2.1 Level AA standards. All functionality can be accessed using only the keyboard.
Keyboard Shortcuts
Key Action Context TabNavigate between UI elements Global Shift + TabNavigate backwards Global ↓ (Down Arrow)Focus next user When list is focused ↑ (Up Arrow)Focus previous user When list is focused EnterSelect/activate focused user When user is focused SpaceToggle selection (in multiple mode) When user is focused EscapeClear search and reset focus When list is focused
Accessibility Features
ARIA Attributes:
role="list" on users container
role="listitem" on each user item
aria-label with user name and status
aria-selected indicates selected users
Proper tabindex management (roving tabindex pattern)
Screen Reader Support:
Announces user details when focused
Announces selection state changes
Announces online/offline status
Semantic HTML structure
Focus Management:
Visible focus indicators (2px border) meeting WCAG contrast requirements
Focus restoration after interactions
Roving tabindex for efficient keyboard navigation
WCAG 2.1 Compliance:
✅ 2.1.1 Keyboard (Level A) - All functionality available via keyboard
✅ 2.1.2 No Keyboard Trap (Level A) - Users can navigate away using keyboard
✅ 2.4.3 Focus Order (Level A) - Logical focus order
✅ 2.4.7 Focus Visible (Level AA) - Visible focus indicators
✅ 4.1.2 Name, Role, Value (Level A) - Proper ARIA attributes
Basic Usage
Simple Implementation
import { Component } from '@angular/core' ;
import { CometChatUsersComponent } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-users' ,
standalone: true ,
imports: [ CometChatUsersComponent ],
template: `
<cometchat-users
(itemClick)="onUserClick($event)"
></cometchat-users>
`
})
export class UsersComponent {
onUserClick ( user : any ) : void {
console . log ( 'Selected user:' , user );
// Navigate to messages view or handle user selection
}
}
See all 19 lines
With Search and Section Headers
< cometchat - users
[ hideSearch ] = "false"
[ showSectionHeader ] = "true"
( itemClick ) = "onUserClick($event)"
( error ) = "onError($event)"
> </ cometchat - users >
Properties
Display Control Properties
Property Type Default Description hideSearchbooleanfalseHide the search bar showSectionHeaderbooleantrueShow alphabetical section headers (A, B, C…) hideErrorbooleanfalseHide error views when errors occur disableLoadingStatebooleanfalseDisable loading state (maintains list during search) hideUserStatusbooleanfalseHide online/offline status indicators showScrollbarbooleanfalseShow/hide scrollbar in user list disableDefaultContextMenubooleantrueWhen true, prevents the browser’s native context menu and shows the custom context menu instead showSelectedUsersPreviewbooleanfalseShow selected users preview chips (multiple mode only)
Data Configuration Properties
Property Type Default Description usersRequestBuilderCometChat.UsersRequestBuilderundefinedCustom request builder for filtering and pagination searchRequestBuilderCometChat.UsersRequestBuilderundefinedCustom request builder specifically for search queries searchKeywordstring''Initial search keyword to filter users sectionHeaderKeykeyof CometChat.User'getName'Key to extract section header value from user object activeUserCometChat.UserundefinedCurrently active/highlighted user selectionModeSelectionMode'none'Selection mode: 'none', 'single', or 'multiple'
Customization Properties
Property Type Default Description options(user: CometChat.User) => CometChatOption[]undefinedFunction to provide custom context menu options
Template Properties
Property Type Default Description headerViewTemplateRef<any>undefinedCustom template for entire header section menuViewTemplateRef<any>undefinedCustom template for menu area in the header (e.g., action buttons, 3-dot menu) loadingViewTemplateRef<any>undefinedCustom template for loading state emptyViewTemplateRef<any>undefinedCustom template for empty state errorViewTemplateRef<any>undefinedCustom template for error state itemViewTemplateRef<{$implicit: CometChat.User}>undefinedCustom template for entire user item leadingViewTemplateRef<{$implicit: CometChat.User}>undefinedCustom template for leading section (avatar area) titleViewTemplateRef<{$implicit: CometChat.User}>undefinedCustom template for title section subtitleViewTemplateRef<{$implicit: CometChat.User}>undefinedCustom template for subtitle section trailingViewTemplateRef<{$implicit: CometChat.User}>undefinedCustom template for trailing section (selection controls)
Events
Event Payload Type Description itemClickCometChat.UserEmitted when a user item is clicked select{user: CometChat.User, selected: boolean}Emitted when a user is selected/deselected errorCometChat.CometChatExceptionEmitted when an error occurs emptyvoidEmitted when the user list is empty after initial fetch selectionChangeSelectionStateEmitted when the selection state changes in selection mode
Usage Patterns
CometChatUsers supports two usage patterns for communicating the selected user to downstream components.
Using Service
Using Props
When a user is selected, ChatStateService stores the active user. Downstream components like cometchat-message-header, cometchat-message-list, and cometchat-message-composer automatically subscribe to the change. import { Component } from '@angular/core' ;
import {
CometChatUsersComponent ,
CometChatMessageHeaderComponent ,
CometChatMessageListComponent ,
CometChatMessageComposerComponent ,
} from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-users-chat' ,
standalone: true ,
imports: [
CometChatUsersComponent ,
CometChatMessageHeaderComponent ,
CometChatMessageListComponent ,
CometChatMessageComposerComponent ,
],
template: `
<div class="chat-layout">
<cometchat-users
(itemClick)="onUserClick($event)"
></cometchat-users>
<div class="chat-panel">
<!-- Auto-subscribe to ChatStateService active user -->
<cometchat-message-header></cometchat-message-header>
<cometchat-message-list></cometchat-message-list>
<cometchat-message-composer></cometchat-message-composer>
</div>
</div>
` ,
})
export class UsersChatComponent {
onUserClick ( user : any ) : void {
// ChatStateService is updated automatically
}
}
See all 37 lines
This is the recommended approach. Selecting a user automatically updates all downstream message components.
Pass [user] directly to downstream components to override ChatStateService state. This is useful when you manage user selection yourself. import { Component } from '@angular/core' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import {
CometChatUsersComponent ,
CometChatMessageHeaderComponent ,
CometChatMessageListComponent ,
CometChatMessageComposerComponent ,
} from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-users-chat' ,
standalone: true ,
imports: [
CometChatUsersComponent ,
CometChatMessageHeaderComponent ,
CometChatMessageListComponent ,
CometChatMessageComposerComponent ,
],
template: `
<div class="chat-layout">
<cometchat-users
(itemClick)="onUserClick($event)"
></cometchat-users>
@if (activeUser) {
<div class="chat-panel">
<cometchat-message-header [user]="activeUser"></cometchat-message-header>
<cometchat-message-list [user]="activeUser"></cometchat-message-list>
<cometchat-message-composer [user]="activeUser"></cometchat-message-composer>
</div>
}
</div>
` ,
})
export class UsersChatComponent {
activeUser : CometChat . User | null = null ;
onUserClick ( user : CometChat . User ) : void {
this . activeUser = user ;
}
}
See all 41 lines
When [user] inputs are provided, they take priority over ChatStateService state for that component instance.
Advanced Usage
Filtering Users with Request Builder
Use the usersRequestBuilder to filter users by various criteria:
import { Component , OnInit } from '@angular/core' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatUsersComponent } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-filtered-users' ,
standalone: true ,
imports: [ CometChatUsersComponent ],
template: `
<cometchat-users
[usersRequestBuilder]="usersBuilder"
(itemClick)="onUserClick($event)"
></cometchat-users>
`
})
export class FilteredUsersComponent implements OnInit {
usersBuilder !: CometChat . UsersRequestBuilder ;
ngOnInit () : void {
// Show only online friends with limit of 20
this . usersBuilder = new CometChat . UsersRequestBuilder ()
. setLimit ( 20 )
. friendsOnly ( true )
. setStatus ( 'online' );
}
onUserClick ( user : CometChat . User ) : void {
console . log ( 'User clicked:' , user );
}
}
See all 30 lines
UserRequestBuilder Methods
Method Type Description setLimitnumberSets the number of users fetched per request (pagination) setSearchKeywordstringFetches users matching the search string hideBlockedUsersbooleanExcludes users blocked by the logged-in user friendsOnlybooleanFetches only friends of the logged-in user setRolesstring[]Fetches users with specified roles setTagsstring[]Fetches users with specified tags withTagsbooleanIncludes tag information in response setStatusstringFilters by status (‘online’ or ‘offline’) setUIDsstring[]Fetches specific users by UIDs
Selection Modes
Enable single or multiple user selection:
import { Component } from '@angular/core' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatUsersComponent , SelectionMode } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-selectable-users' ,
standalone: true ,
imports: [ CometChatUsersComponent ],
template: `
<div class="user-selection">
@if (selectedUsers.length > 0) {
<div class="toolbar">
<span>{{ selectedUsers.length }} users selected</span>
<button (click)="createGroup()">Create Group</button>
</div>
}
<cometchat-users
[selectionMode]="selectionMode"
[showSelectedUsersPreview]="true"
(select)="onUserSelect($event)"
(itemClick)="onUserClick($event)"
></cometchat-users>
</div>
`
})
export class SelectableUsersComponent {
selectionMode = SelectionMode . multiple ;
selectedUsers : CometChat . User [] = [];
onUserSelect ( event : { user : CometChat . User ; selected : boolean }) : void {
if ( event . selected ) {
this . selectedUsers . push ( event . user );
} else {
this . selectedUsers = this . selectedUsers . filter (
u => u . getUid () !== event . user . getUid ()
);
}
}
onUserClick ( user : CometChat . User ) : void {
console . log ( 'User clicked:' , user );
}
createGroup () : void {
console . log ( 'Creating group with users:' , this . selectedUsers );
// Implement group creation logic
}
}
See all 49 lines
Shift-Click Range Selection
In multiple selection mode, users can use Shift+Click to select a range of users:
Click on a user to set the anchor point
Hold Shift and click on another user
All users between the anchor and clicked user will be selected/deselected
This feature is built-in and requires no additional configuration.
Provide custom actions for each user:
import { Component } from '@angular/core' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatUsersComponent , CometChatOption } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-custom-menu-users' ,
standalone: true ,
imports: [ CometChatUsersComponent ],
template: `
<cometchat-users
[options]="getCustomOptions"
(itemClick)="onUserClick($event)"
></cometchat-users>
`
})
export class CustomMenuUsersComponent {
getCustomOptions = ( user : CometChat . User ) : CometChatOption [] => {
return [
{
id: 'message' ,
title: 'Send Message' ,
iconURL: 'assets/message-icon.svg' ,
onClick : () => this . sendMessage ( user )
},
{
id: 'call' ,
title: 'Start Call' ,
iconURL: 'assets/call-icon.svg' ,
onClick : () => this . startCall ( user )
},
{
id: 'block' ,
title: 'Block User' ,
iconURL: 'assets/block-icon.svg' ,
onClick : () => this . blockUser ( user )
}
];
};
sendMessage ( user : CometChat . User ) : void {
console . log ( 'Sending message to:' , user . getName ());
}
startCall ( user : CometChat . User ) : void {
console . log ( 'Starting call with:' , user . getName ());
}
blockUser ( user : CometChat . User ) : void {
console . log ( 'Blocking user:' , user . getName ());
}
onUserClick ( user : CometChat . User ) : void {
console . log ( 'User clicked:' , user );
}
}
See all 55 lines
Customization with Templates
Custom Subtitle View
Customize the subtitle section to show additional user information:
import { Component } from '@angular/core' ;
import { CommonModule } from '@angular/common' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatUsersComponent } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-custom-subtitle' ,
standalone: true ,
imports: [ CommonModule , CometChatUsersComponent ],
template: `
<cometchat-users
[subtitleView]="customSubtitle"
(itemClick)="onUserClick($event)"
>
<ng-template #customSubtitle let-user>
<div class="custom-subtitle">
<span class="status" [class.online]="user.getStatus() === 'online'">
{{ user.getStatus() }}
</span>
@if (user.getStatus() !== 'online') {
<span class="last-active">
Last seen: {{ formatLastActive(user.getLastActiveAt()) }}
</span>
}
</div>
</ng-template>
</cometchat-users>
` ,
styles: [ `
.custom-subtitle {
display: flex;
align-items: center;
gap: 8px;
font-size: 12px;
}
.status {
color: #999;
text-transform: capitalize;
}
.status.online {
color: #4CAF50;
}
.last-active {
color: #666;
}
` ]
})
export class CustomSubtitleComponent {
formatLastActive ( timestamp : number ) : string {
if ( ! timestamp ) return 'Unknown' ;
const date = new Date ( timestamp * 1000 );
return date . toLocaleDateString ();
}
onUserClick ( user : CometChat . User ) : void {
console . log ( 'User clicked:' , user );
}
}
See all 58 lines
Custom Leading View
Customize the avatar and status indicator area:
import { Component } from '@angular/core' ;
import { CommonModule } from '@angular/common' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatUsersComponent , CometChatAvatarComponent } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-custom-leading' ,
standalone: true ,
imports: [ CommonModule , CometChatUsersComponent , CometChatAvatarComponent ],
template: `
<cometchat-users
[leadingView]="customLeading"
(itemClick)="onUserClick($event)"
>
<ng-template #customLeading let-user>
<div class="custom-leading">
<div class="avatar-wrapper">
<cometchat-avatar
[image]="user.getAvatar()"
[name]="user.getName()"
></cometchat-avatar>
@if (user.getStatus() === 'online') {
<span class="online-badge"></span>
}
</div>
@if (user.getRole()) {
<span class="role-badge">
{{ user.getRole() }}
</span>
}
</div>
</ng-template>
</cometchat-users>
` ,
styles: [ `
.custom-leading {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
}
.avatar-wrapper {
position: relative;
}
.online-badge {
position: absolute;
bottom: 2px;
right: 2px;
width: 10px;
height: 10px;
background-color: #4CAF50;
border: 2px solid white;
border-radius: 50%;
}
.role-badge {
margin-top: 4px;
padding: 2px 6px;
background-color: #6852D6;
color: white;
font-size: 8px;
font-weight: 600;
border-radius: 4px;
text-transform: uppercase;
}
` ]
})
export class CustomLeadingComponent {
onUserClick ( user : CometChat . User ) : void {
console . log ( 'User clicked:' , user );
}
}
See all 71 lines
Custom Trailing View
Customize the trailing section with action buttons:
import { Component } from '@angular/core' ;
import { CommonModule } from '@angular/common' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatUsersComponent , CometChatButtonComponent } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-custom-trailing' ,
standalone: true ,
imports: [ CommonModule , CometChatUsersComponent , CometChatButtonComponent ],
template: `
<cometchat-users
[trailingView]="customTrailing"
(itemClick)="onUserClick($event)"
>
<ng-template #customTrailing let-user>
<div class="custom-trailing">
<cometchat-button
[iconURL]="'assets/chat-icon.svg'"
(click)="startChat(user); $event.stopPropagation()"
></cometchat-button>
<cometchat-button
[iconURL]="'assets/call-icon.svg'"
(click)="startCall(user); $event.stopPropagation()"
></cometchat-button>
</div>
</ng-template>
</cometchat-users>
` ,
styles: [ `
.custom-trailing {
display: flex;
gap: 8px;
}
` ]
})
export class CustomTrailingComponent {
startChat ( user : CometChat . User ) : void {
console . log ( 'Starting chat with:' , user . getName ());
}
startCall ( user : CometChat . User ) : void {
console . log ( 'Starting call with:' , user . getName ());
}
onUserClick ( user : CometChat . User ) : void {
console . log ( 'User clicked:' , user );
}
}
See all 48 lines
Custom Empty and Error States
Provide custom views for empty and error states:
import { Component } from '@angular/core' ;
import { CommonModule } from '@angular/common' ;
import { CometChatUsersComponent } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-custom-states' ,
standalone: true ,
imports: [ CommonModule , CometChatUsersComponent ],
template: `
<cometchat-users
[emptyView]="customEmpty"
[errorView]="customError"
(itemClick)="onUserClick($event)"
(error)="onError($event)"
>
<ng-template #customEmpty>
<div class="custom-empty-state">
<img src="assets/no-users.svg" alt="No users" />
<h3>No Users Found</h3>
<p>There are no users available at the moment</p>
<button (click)="refreshUsers()">Refresh</button>
</div>
</ng-template>
<ng-template #customError>
<div class="custom-error-state">
<img src="assets/error-icon.svg" alt="Error" />
<h3>Something went wrong</h3>
<p>We couldn't load the users list</p>
<button (click)="retryLoading()">Try Again</button>
</div>
</ng-template>
</cometchat-users>
` ,
styles: [ `
.custom-empty-state,
.custom-error-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 40px 20px;
text-align: center;
}
.custom-empty-state img,
.custom-error-state img {
width: 100px;
height: 100px;
margin-bottom: 16px;
}
.custom-empty-state h3,
.custom-error-state h3 {
font-size: 18px;
font-weight: 600;
margin: 0 0 8px 0;
color: #333;
}
.custom-empty-state p,
.custom-error-state p {
font-size: 14px;
color: #666;
margin: 0 0 16px 0;
}
button {
padding: 10px 24px;
background-color: #6852D6;
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
}
button:hover {
background-color: #5742B8;
}
` ]
})
export class CustomStatesComponent {
refreshUsers () : void {
console . log ( 'Refreshing users' );
// Trigger refresh
}
retryLoading () : void {
console . log ( 'Retrying to load users' );
// Trigger retry
}
onUserClick ( user : any ) : void {
console . log ( 'User clicked:' , user );
}
onError ( error : any ) : void {
console . error ( 'Error:' , error );
}
}
See all 95 lines
Styling with CSS Variables
The CometChatUsers component uses CSS variables for comprehensive theming:
cometchat-users {
/* Background colors */
--cometchat-background-color-01 : #ffffff ;
--cometchat-background-color-02 : #f5f5f5 ;
--cometchat-background-color-03 : #e8e8e8 ;
/* Text colors */
--cometchat-text-color-primary : #141414 ;
--cometchat-text-color-secondary : #727272 ;
/* Border colors */
--cometchat-border-color-light : #e8e8e8 ;
/* Primary color */
--cometchat-primary-color : #6852D6 ;
/* Status colors */
--cometchat-success-color : #09C26F ;
--cometchat-neutral-color-300 : #999999 ;
/* Typography */
--cometchat-font-heading2-bold : 700 20 px / 24 px Roboto;
--cometchat-font-body-regular : 400 14 px / 16.8 px Roboto;
--cometchat-font-caption1-medium : 500 12 px / 14.4 px Roboto;
/* Spacing */
--cometchat-spacing-1 : 4 px ;
--cometchat-spacing-2 : 8 px ;
--cometchat-spacing-3 : 12 px ;
--cometchat-spacing-4 : 16 px ;
/* Border radius */
--cometchat-radius-2 : 8 px ;
--cometchat-radius-max : 1000 px ;
}
See all 35 lines
Dark Theme Example
.dark-theme cometchat-users {
--cometchat-background-color-01 : #1a1a1a ;
--cometchat-background-color-02 : #2a2a2a ;
--cometchat-background-color-03 : #333333 ;
--cometchat-text-color-primary : #ffffff ;
--cometchat-text-color-secondary : #cccccc ;
--cometchat-border-color-light : #444444 ;
}
Custom Brand Colors
.branded-users cometchat-users {
--cometchat-primary-color : #FF6B35 ;
--cometchat-success-color : #00C853 ;
}
Real-Time Features
Automatic Updates
The component automatically updates in real-time for:
User Status : Online/offline status changes are reflected immediately
User Blocked/Unblocked : Updates when users are blocked or unblocked via CometChatUserEvents
Connection Recovery : Automatically refreshes the list when connection is re-established
Event Subscriptions
The component subscribes to the following events:
// SDK UserListener events
CometChat . UserListener . onUserOnline ( user )
CometChat . UserListener . onUserOffline ( user )
// CometChatUserEvents
CometChatUserEvents . ccUserBlocked
CometChatUserEvents . ccUserUnblocked
// Connection events
CometChat . ConnectionListener . onConnected ()
See all 10 lines
Error Handling
Built-in Error Handling
The component includes comprehensive error handling:
< cometchat - users
[ hideError ] = "false"
( error ) = "handleError($event)"
( itemClick ) = "onUserClick($event)"
> </ cometchat - users >
handleError ( error : CometChat . CometChatException ): void {
console . error ( 'Users error:' , error );
if ( error . code === 'NETWORK_ERROR' ) {
this . showToast ( 'Network error. Please check your connection.' );
} else if ( error . code === 'AUTH_ERROR' ) {
this . showToast ( 'Authentication error. Please log in again.' );
} else {
this . showToast ( 'An error occurred. Please try again.' );
}
}
See all 11 lines
Best Practices
Use usersRequestBuilder to limit the initial fetch size for better performance. The default limit is 30 users per page.
Always handle the error event to provide feedback to users when something goes wrong.
The component uses OnPush change detection strategy for optimal performance. If you’re using custom templates with external state, ensure proper change detection triggering.
Use showSelectedUsersPreview with selectionMode="multiple" to provide visual feedback of selected users.
When using custom context menu options, ensure the onClick handlers are properly bound to avoid this context issues. Use arrow functions.
Complete Example
Here’s a comprehensive example combining multiple features:
import { Component , OnInit , OnDestroy } from '@angular/core' ;
import { CommonModule } from '@angular/common' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import {
CometChatUsersComponent ,
SelectionMode ,
CometChatOption
} from '@cometchat/chat-uikit-angular' ;
import { Subject , takeUntil } from 'rxjs' ;
@ Component ({
selector: 'app-users-demo' ,
standalone: true ,
imports: [ CommonModule , CometChatUsersComponent ],
template: `
<div class="users-container">
@if (selectedUsers.length > 0) {
<div class="toolbar">
<span>{{ selectedUsers.length }} selected</span>
<button (click)="createGroupChat()">Create Group</button>
<button (click)="clearSelection()">Clear</button>
</div>
}
<cometchat-users
[usersRequestBuilder]="usersBuilder"
[selectionMode]="selectionMode"
[showSelectedUsersPreview]="true"
[showSectionHeader]="true"
[options]="getCustomOptions"
[subtitleView]="customSubtitle"
(itemClick)="onUserClick($event)"
(select)="onUserSelect($event)"
(error)="handleError($event)"
(empty)="handleEmpty()"
>
<ng-template #customSubtitle let-user>
<div class="user-subtitle">
<span [class.online]="user.getStatus() === 'online'">
{{ user.getStatus() }}
</span>
</div>
</ng-template>
</cometchat-users>
</div>
` ,
styles: [ `
.users-container {
height: 100vh;
display: flex;
flex-direction: column;
}
.toolbar {
display: flex;
align-items: center;
gap: 12px;
padding: 12px 16px;
background-color: #f5f5f5;
border-bottom: 1px solid #e8e8e8;
}
.toolbar span {
flex: 1;
font-weight: 500;
}
.toolbar button {
padding: 8px 16px;
border: none;
border-radius: 6px;
cursor: pointer;
}
.toolbar button:first-of-type {
background-color: #6852D6;
color: white;
}
.toolbar button:last-of-type {
background-color: #e8e8e8;
}
.user-subtitle {
font-size: 12px;
color: #666;
}
.user-subtitle .online {
color: #4CAF50;
}
` ]
})
export class UsersDemoComponent implements OnInit , OnDestroy {
usersBuilder !: CometChat . UsersRequestBuilder ;
selectionMode = SelectionMode . multiple ;
selectedUsers : CometChat . User [] = [];
private destroy$ = new Subject < void >();
ngOnInit () : void {
this . usersBuilder = new CometChat . UsersRequestBuilder ()
. setLimit ( 30 )
. hideBlockedUsers ( true );
}
ngOnDestroy () : void {
this . destroy$ . next ();
this . destroy$ . complete ();
}
getCustomOptions = ( user : CometChat . User ) : CometChatOption [] => {
return [
{
id: 'message' ,
title: 'Message' ,
iconURL: 'assets/chat.svg' ,
onClick : () => this . startChat ( user )
},
{
id: 'block' ,
title: 'Block' ,
iconURL: 'assets/block.svg' ,
onClick : () => this . blockUser ( user )
}
];
};
onUserClick ( user : CometChat . User ) : void {
console . log ( 'User clicked:' , user . getName ());
}
onUserSelect ( event : { user : CometChat . User ; selected : boolean }) : void {
if ( event . selected ) {
this . selectedUsers . push ( event . user );
} else {
this . selectedUsers = this . selectedUsers . filter (
u => u . getUid () !== event . user . getUid ()
);
}
}
handleError ( error : CometChat . CometChatException ) : void {
console . error ( 'Error:' , error );
}
handleEmpty () : void {
console . log ( 'No users found' );
}
startChat ( user : CometChat . User ) : void {
console . log ( 'Starting chat with:' , user . getName ());
}
blockUser ( user : CometChat . User ) : void {
console . log ( 'Blocking:' , user . getName ());
}
createGroupChat () : void {
console . log ( 'Creating group with:' , this . selectedUsers . map ( u => u . getName ()));
}
clearSelection () : void {
this . selectedUsers = [];
}
}
See all 159 lines
CometChatGroups : List and select groups
CometChatConversations : Display conversations list
CometChatMessageList : Display messages for a selected user
CometChatAvatar : Avatar component used in user items
CometChatListItem : List item component used for rendering users
Technical Details
Standalone Component : Can be imported and used independently
Change Detection : Uses OnPush strategy for optimal performance
Manager Architecture : UsersManager handles SDK interactions
Real-time Updates : Automatic via SDK listeners
Pagination : Automatic on scroll with intersection observers
Accessibility : WCAG 2.1 Level AA compliant
BEM CSS : Follows Block Element Modifier naming convention