@libs-ui/components-avatar
v0.2.357-35
Published
> Component hiển thị avatar (ảnh đại diện) với cơ chế fallback thông minh sang text/icon khi ảnh lỗi hoặc không có.
Readme
@libs-ui/components-avatar
Component hiển thị avatar (ảnh đại diện) với cơ chế fallback thông minh sang text/icon khi ảnh lỗi hoặc không có.
Giới thiệu
LibsUiComponentsAvatarComponent là standalone Angular component dùng để hiển thị ảnh đại diện người dùng. Component hỗ trợ nhiều kích thước và hình dạng, tự động fallback sang text với màu nền được generate từ ID khi ảnh không tải được, và tích hợp gallery viewer để xem ảnh phóng to khi click.
Tính năng
- Hiển thị ảnh avatar từ URL với xử lý lỗi tự động
- Fallback thông minh theo chuỗi:
linkAvatar→linkAvatarError→ text + màu nền từidGenColor - Hỗ trợ 6 kích thước: 16, 24, 32, 40, 48, 64px
- Hỗ trợ 2 hình dạng:
circle(mặc định) vàrectangle - Tự động generate màu nền nhất quán từ ID (hash color — cùng ID luôn ra cùng màu)
- Font size của text fallback tự động điều chỉnh theo kích thước avatar
- Preview ảnh phóng to khi click (tích hợp
LibsUiComponentsGalleryViewerComponent) - Angular Signals + Standalone Component
Khi nào sử dụng
- Hiển thị ảnh đại diện người dùng trong danh sách, comment, profile
- Hiển thị avatar có fallback khi ảnh không tải được hoặc chưa có ảnh
- Cần hiển thị avatar với nhiều kích thước khác nhau trong cùng giao diện
- Cần cho phép người dùng xem ảnh phóng to khi click vào avatar
Cài đặt
npm install @libs-ui/components-avatarImport
import {
LibsUiComponentsAvatarComponent,
IAvatarConfig,
TYPE_SHAPE_AVATAR,
TYPE_SIZE_AVATAR_CONFIG,
} from '@libs-ui/components-avatar';
@Component({
standalone: true,
imports: [LibsUiComponentsAvatarComponent],
// ...
})
export class MyComponent {}Ví dụ sử dụng
1. Avatar cơ bản với ảnh
<libs_ui-components-avatar
[linkAvatar]="'https://example.com/user-123.jpg'"
[size]="40" />2. Avatar với fallback text (khi ảnh lỗi)
Khi linkAvatar lỗi và không có linkAvatarError, component sẽ hiển thị ký tự đầu của textAvatar trên nền màu được generate từ idGenColor.
<libs_ui-components-avatar
[linkAvatar]="'https://example.com/user-123.jpg'"
[textAvatar]="'Nguyễn Văn An'"
[idGenColor]="'user-123'"
[size]="40"
(outAvatarError)="handlerAvatarError()" />handlerAvatarError(): void {
// Ảnh không tải được, component đã tự hiển thị text fallback
console.log('Avatar fallback to text');
}3. Avatar với ảnh dự phòng và text cuối cùng
<!-- getLastTextAfterSpace PHẢI được truyền TRƯỚC textAvatar -->
<libs_ui-components-avatar
[linkAvatar]="'https://example.com/user-456.jpg'"
[linkAvatarError]="'https://example.com/default-avatar.png'"
[getLastTextAfterSpace]="true"
[textAvatar]="'Trần Thị Bích'"
[idGenColor]="'user-456'"
[size]="40" />Khi getLastTextAfterSpace = true, text 'Trần Thị Bích' sẽ lấy ký tự đầu của từ cuối cùng → hiển thị B.
4. Avatar hình chữ nhật
<libs_ui-components-avatar
[linkAvatar]="'https://example.com/company-logo.jpg'"
[typeShape]="'rectangle'"
[size]="48" />5. Avatar có thể click để xem phóng to
<libs_ui-components-avatar
[linkAvatar]="'https://example.com/user-photo.jpg'"
[clickPreviewImage]="true"
[zIndexPreviewImage]="1050"
[size]="64"
(outEventPreviewImage)="handlerPreviewImageEvent($event)" />handlerPreviewImageEvent(state: 'open' | 'remove'): void {
if (state === 'open') {
console.log('Gallery viewer mở');
} else {
console.log('Gallery viewer đóng');
}
}6. Danh sách avatar người dùng
import { Component } from '@angular/core';
import { LibsUiComponentsAvatarComponent } from '@libs-ui/components-avatar';
interface User {
id: string;
name: string;
avatarUrl: string;
}
@Component({
standalone: true,
imports: [LibsUiComponentsAvatarComponent],
template: `
<div class="flex items-center gap-2">
@for (user of users; track user.id) {
<libs_ui-components-avatar
[linkAvatar]="user.avatarUrl"
[textAvatar]="user.name"
[idGenColor]="user.id"
[classInclude]="''"
[size]="32" />
}
</div>
`,
})
export class UserListComponent {
users: User[] = [
{ id: 'u1', name: 'Nguyen Van A', avatarUrl: 'https://example.com/u1.jpg' },
{ id: 'u2', name: 'Tran Thi B', avatarUrl: 'https://example.com/u2.jpg' },
{ id: 'u3', name: 'Le Van C', avatarUrl: 'https://example.com/u3.jpg' },
];
}7. Tùy chỉnh class CSS
<libs_ui-components-avatar
[linkAvatar]="'https://example.com/avatar.jpg'"
[size]="40"
[classInclude]="'mr-0'"
[classImageInclude]="'opacity-90'"
[textAvatarClassInclude]="'font-bold'"
[containerTextAvatarClassInclude]="'border border-white'" />@Input()
| Input | Type | Default | Mô tả | Ví dụ |
|---|---|---|---|---|
| [classInclude] | string \| undefined | 'mr-[8px]' | Class CSS tùy chỉnh cho thẻ container ngoài cùng | [classInclude]="'mr-0 mb-2'" |
| [classImageInclude] | string \| undefined | '' | Class CSS tùy chỉnh cho thẻ <img> | [classImageInclude]="'opacity-80'" |
| [clickPreviewImage] | boolean \| undefined | undefined | Bật tính năng click để xem ảnh phóng to qua gallery viewer | [clickPreviewImage]="true" |
| [containerTextAvatarClassInclude] | string \| undefined | '' | Class CSS tùy chỉnh cho container bọc ngoài text fallback | [containerTextAvatarClassInclude]="'border-2'" |
| [getLastTextAfterSpace] | boolean \| undefined | undefined | Lấy từ cuối cùng (sau khoảng trắng cuối) để hiển thị ký tự đầu. Phải truyền TRƯỚC textAvatar | [getLastTextAfterSpace]="true" |
| [idGenColor] | string \| undefined | undefined | ID dùng để generate màu nền khi hiển thị text fallback. Cùng ID luôn ra cùng màu | [idGenColor]="'user-123'" |
| [linkAvatar] | string \| undefined | undefined | URL ảnh avatar chính | [linkAvatar]="user.photoUrl" |
| [linkAvatarError] | string \| undefined | undefined | URL ảnh dự phòng khi linkAvatar bị lỗi | [linkAvatarError]="'/assets/default.png'" |
| [size] | TYPE_SIZE_AVATAR_CONFIG \| undefined | 32 | Kích thước (px) của avatar. Chỉ chấp nhận các giá trị: 16, 24, 32, 40, 48, 64 | [size]="40" |
| [textAvatar] | string \| undefined | '' | Text dùng để hiển thị ký tự đầu khi fallback. Tự động loại bỏ unicode và ký tự đặc biệt | [textAvatar]="user.fullName" |
| [textAvatarClassInclude] | string \| undefined | '' | Class CSS tùy chỉnh cho phần tử chứa ký tự text fallback | [textAvatarClassInclude]="'tracking-wide'" |
| [typeShape] | TYPE_SHAPE_AVATAR \| undefined | 'circle' | Hình dạng của avatar: 'circle' (border-radius 50%) hoặc 'rectangle' (border-radius 4px) | [typeShape]="'rectangle'" |
| [zIndexPreviewImage] | number \| undefined | undefined | Z-index cho gallery viewer khi xem ảnh phóng to. Cần set khi giao diện có overlay/modal | [zIndexPreviewImage]="1050" |
@Output()
| Output | Type | Mô tả | Handler TS | Binding HTML |
|---|---|---|---|---|
| (outAvatarError) | void | Phát ra khi tất cả nguồn ảnh đều thất bại (cả linkAvatar lẫn linkAvatarError) và component chuyển sang hiển thị text fallback | handlerAvatarError(): void { console.log('Avatar fallback'); } | (outAvatarError)="handlerAvatarError()" |
| (outEventPreviewImage) | 'open' \| 'remove' | Phát ra khi gallery viewer được mở ('open') hoặc đóng ('remove') | handlerPreviewImageEvent(state: 'open' \| 'remove'): void { console.log(state); } | (outEventPreviewImage)="handlerPreviewImageEvent($event)" |
Types & Interfaces
import {
IAvatarConfig,
TYPE_SHAPE_AVATAR,
TYPE_SIZE_AVATAR_CONFIG,
} from '@libs-ui/components-avatar';
// Kích thước được hỗ trợ (px)
// Font size text fallback tự động: 16/24 → h6s, 32 → h4s, 40 → h3s, 64 → h1s, mặc định → h4s
export type TYPE_SIZE_AVATAR_CONFIG = 16 | 24 | 32 | 40 | 48 | 64;
// Hình dạng avatar
// 'circle' → border-radius: 50%
// 'rectangle' → border-radius: 4px
export type TYPE_SHAPE_AVATAR = 'circle' | 'rectangle';
// Interface config dùng khi cần truyền object config từ component cha
export interface IAvatarConfig {
classImageInclude?: string;
classInclude?: string;
size?: TYPE_SIZE_AVATAR_CONFIG;
linkAvatar?: string;
linkAvatarError?: string;
idGenColor?: string;
textAvatar?: string;
typeShape?: TYPE_SHAPE_AVATAR;
getLastTextAfterSpace?: boolean;
}Ví dụ dùng IAvatarConfig để truyền config từ component cha:
// parent.component.ts
import { IAvatarConfig } from '@libs-ui/components-avatar';
avatarConfig: IAvatarConfig = {
linkAvatar: 'https://example.com/avatar.jpg',
textAvatar: 'Nguyen Van An',
idGenColor: 'user-001',
size: 40,
typeShape: 'circle',
};<!-- parent.component.html -->
<libs_ui-components-avatar
[linkAvatar]="avatarConfig.linkAvatar"
[textAvatar]="avatarConfig.textAvatar"
[idGenColor]="avatarConfig.idGenColor"
[size]="avatarConfig.size"
[typeShape]="avatarConfig.typeShape" />Lưu ý quan trọng
⚠️ Thứ tự input getLastTextAfterSpace: Input [getLastTextAfterSpace] PHẢI được khai báo trong template TRƯỚC [textAvatar]. Nếu khai báo sau, transform của textAvatar sẽ chạy trước khi đọc được giá trị getLastTextAfterSpace, dẫn đến kết quả sai.
⚠️ Chuỗi fallback xử lý lỗi ảnh: Component xử lý lỗi theo thứ tự: linkAvatar → (lỗi) → linkAvatarError → (lỗi) → hiển thị text từ textAvatar với màu nền từ idGenColor. Nếu không cung cấp idGenColor và textAvatar, output (outAvatarError) sẽ phát ra ngay sau lần lỗi đầu tiên mà không hiển thị fallback.
⚠️ Màu nền nhất quán: Màu nền khi hiển thị text fallback được tính từ idGenColor qua hàm hash. Cùng một giá trị idGenColor luôn cho ra cùng một màu, đảm bảo nhất quán giao diện giữa các lần render.
⚠️ Preview image và lifecycle: Khi [clickPreviewImage]="true", component tự khởi tạo và quản lý vòng đời của LibsUiComponentsGalleryViewerComponent. Gallery viewer sẽ tự bị hủy khi avatar component bị destroy (xử lý trong ngOnDestroy).
⚠️ Transform text: textAvatar được tự động xử lý: loại bỏ unicode tiếng Việt (normalize), xóa ký tự đặc biệt (giữ lại chữ và số), trim khoảng trắng, rồi lấy ký tự đầu tiên. Nếu sau xử lý không còn ký tự nào, hiển thị —.
