Cấu hình pagination
Constructor này chịu trách nhiệm:
options)pages → dùng dữ liệu tĩnhpageLoader + totalPagestotalPages ban đầuCó 2 cách sử dụng chính:
Khi bạn đã có sẵn toàn bộ dữ liệu:
pages sẽ được ưu tiêntotalPages được tính tự động từ pages.lengthKhi dữ liệu đến từ API / database:
totalPagespageLoader sẽ được gọi khi cần load trang⚠️ Nếu không cung cấp pages và cũng không có pageLoader
thì hệ thống sẽ không có nguồn dữ liệu và sẽ throw error khi chạy.
// Dùng dữ liệu tĩnh
const pagination = new PaginationBuilder<string>({
pages: ["Trang 1", "Trang 2", "Trang 3"],
renderPage: ({ data }) => ({ content: data })
});
Xóa toàn bộ cache của pagination
void
Method này sẽ xóa toàn bộ dữ liệu đã cache trong pageCache.
Cache được sử dụng khi:
pageLoaderDùng khi:
⚠️ Sau khi gọi:
getPageData tiếp theo sẽ gọi lại pageLoaderChuyển đến trang đầu tiên
Optionalinteraction: StringSelectMenuInteraction<CacheType> | ButtonInteraction<CacheType>Interaction (button hoặc select menu) nếu có
Promise
Lấy context hiện tại của pagination
Promise<PaginationRenderContext
Method này trả về object context giống như khi gọi renderPage.
Bao gồm:
page: trang hiện tạitotalPages: tổng số trangdata: dữ liệu trang hiện tạipagination: instance hiện tạiDùng khi:
Lấy message hiện tại của pagination
Message Message Discord đã được gửi
Đây là message được tạo ra khi gọi start().
⚠️ Method này chỉ hợp lệ sau khi đã gọi start().
Nếu gọi trước đó có thể trả về undefined hoặc gây lỗi.
Dùng khi:
Lấy dữ liệu của một trang cụ thể
Số trang (0-based index)
Promise
Đây là method core chịu trách nhiệm truy xuất dữ liệu cho pagination.
Method này hỗ trợ 2 nguồn dữ liệu:
pages: dữ liệu tĩnh (array có sẵn)pageLoader: dữ liệu động (load theo từng page)Đồng thời tích hợp cơ chế cache (nếu useCache = true) để tối ưu hiệu năng.
Luồng xử lý:
pages)pagepages[page]pageLoader)useCache = true và đã có cache → trả về cache (cache hit)pageLoader(page) (cache miss)⚠️ Cache sử dụng Collection<number, T> với key là index của page.
// Sử dụng dữ liệu tĩnh
const pagination = new PaginationBuilder<string>({
pages: ["A", "B", "C"],
renderPage: ({ data }) => ({ content: data })
});
await pagination.getPageData(1); // "B"
// Sử dụng dữ liệu động + cache
const pagination = new PaginationBuilder<string[]>({
totalPages: 5,
useCache: true,
pageLoader: async (page) => {
console.log("Loading page:", page);
return [`Item ${page}`];
},
renderPage: ({ data }) => ({
content: data.join("\n")
})
});
await pagination.getPageData(0); // gọi pageLoader
await pagination.getPageData(0); // dùng cache
Chuyển đến một trang cụ thể và cập nhật message
Số trang cần chuyển đến (0-based)
Optionalinteraction: StringSelectMenuInteraction<CacheType> | ButtonInteraction<CacheType>Interaction (button hoặc select menu) nếu có
Promise
Đây là method trung tâm (core) của hệ thống pagination.
Hầu hết các hành động điều hướng như:
next()prev()first()last()đều gọi vào method này.
Quy trình hoạt động:
page < 0 → set về 0page >= totalPages → set về totalPages - 1oldPagethis.page = pagegetPageData(page)renderPageinteraction → dùng interaction.update()message.edit()onPageChange (nếu có)⚠️ Method này không tạo collector mới, chỉ update UI.
// Dùng trong custom button
onComponent: async ({ interaction, pagination }) => {
if (interaction.customId === "go:page5") {
await pagination.goto(4, interaction);
}
}
// Boundary handling
await pagination.goto(-10); // => page = 0
await pagination.goto(999); // => page = last
Kiểm tra trạng thái hoạt động của pagination
boolean true nếu pagination đang chạy, ngược lại false
Method này dùng để xác định xem InteractionCollector
của pagination còn hoạt động hay không.
Điều kiện để trả về true:
collector đã được khởi tạocollector chưa bị kết thúc (ended = false)Dùng khi:
⚠️ Method này không đảm bảo message còn tồn tại, chỉ kiểm tra trạng thái collector.
Chuyển đến trang cuối cùng
Optionalinteraction: StringSelectMenuInteraction<CacheType> | ButtonInteraction<CacheType>Interaction (button hoặc select menu) nếu có
Promise
Chuyển sang trang tiếp theo
Optionalinteraction: StringSelectMenuInteraction<CacheType> | ButtonInteraction<CacheType>Interaction (button hoặc select menu) nếu có
Promise
Đây là method helper, thực chất gọi:
goto(this.page + 1)
Dùng khi:
⚠️ Nếu đang ở trang cuối:
goto clamp boundary)Xử lý lỗi phát sinh trong quá trình thực thi
Đối tượng lỗi nhận được (unknown)
Giá trị trả về từ options.onError nếu được cung cấp, ngược lại sẽ trả về undefined
Method này đóng vai trò là wrapper để gọi callback onError
được truyền vào thông qua options.
Nếu onError không được định nghĩa, method sẽ không thực hiện
bất kỳ xử lý nào và trả về undefined.
Method không tự xử lý hoặc log lỗi — toàn bộ logic xử lý
phụ thuộc vào implementation của options.onError.
Dùng khi:
⚠️ Không có cơ chế fallback nếu onError không tồn tại.
Cần đảm bảo xử lý lỗi ở nơi gọi nếu cần thiết.
Quay lại trang trước
Optionalinteraction: StringSelectMenuInteraction<CacheType> | ButtonInteraction<CacheType>Interaction (button hoặc select menu) nếu có
Promise
Đây là method helper, thực chất gọi:
goto(this.page - 1)
Dùng khi:
⚠️ Nếu đang ở trang đầu:
goto clamp boundary)Chỉ cập nhật lại components (buttons, select menu) của message hiện tại.
Wrapper của reloadPartial với { components: true }.
Method này:
message.edit chỉ với componentsKhông gọi renderPage, nên:
Phù hợp khi:
Re-render toàn bộ message (content + components) của trang hiện tại.
Wrapper của reloadPartial với { content: true, components: true }.
Method này sẽ:
renderPage)message.editKhông thay đổi page hay trạng thái pagination.
Re-render lại nội dung (content / embed) của message hiện tại.
Wrapper của reloadPartial với { content: true }.
Method này:
renderPageKhông thay đổi:
Phù hợp khi:
Cập nhật một phần message (content và/hoặc components)
Cấu hình phần cần update
Optionalcomponents?: booleanCập nhật components (buildComponents)
Optionalcontent?: booleanCập nhật nội dung (renderPage)
Promise
Method này cho phép update riêng lẻ hoặc đồng thời:
Flow thực thi:
getPageDatarenderPage (nếu cần content)buildComponents (nếu cần components)message.edit để apply thay đổiKhi update content:
components từ renderPage sẽ bị loại bỏcomponents được build riêngDùng khi:
⚠️ Lưu ý:
false hoặc không truyền → không làm gìrenderPage và buildComponents phải trả về dữ liệu hợp lệmessage phải còn tồn tại và editableKhởi động hệ thống pagination và gửi message ban đầu
Message hoặc ChatInputCommandInteraction dùng để reply
Promise
Đây là method entry point (điểm bắt đầu) của toàn bộ PaginationBuilder.
Khi gọi method này, hệ thống sẽ:
page = 0)renderPage để tạo nội dung messageInteractionCollector để lắng nghe interactiononStart (nếu có)Method này phải được gọi sau khi bạn đã cấu hình đầy đủ:
renderPage (bắt buộc)pages hoặc pageLoaderNó hỗ trợ 2 nguồn gọi:
Message: dùng trong message commandChatInputCommandInteraction: dùng trong slash command⚠️ Sau khi gọi start, pagination sẽ bắt đầu hoạt động
và người dùng có thể tương tác ngay lập tức.
// Ví dụ đầy đủ
const pagination = new PaginationBuilder<string[]>({
totalPages: 5,
pageLoader: async (page) => {
return Array.from({ length: 5 }, (_, i) => `Item ${page}-${i}`);
},
renderPage: ({ data, page, totalPages }) => ({
content: `Trang ${page + 1}/${totalPages}\n\n` + data.join("\n")
}),
onStart: ({ message }) => {
console.log("Pagination started:", message.id);
}
});
await pagination.start(interaction);
Dừng pagination và vô hiệu hóa toàn bộ interaction
Promise
Method này dùng để kết thúc vòng đời của pagination.
Nó sẽ:
InteractionCollector (ngừng nhận interaction)onStop (nếu có)Dùng khi:
⚠️ Sau khi gọi stop():
message.edit thất bại → sẽ được catch và chuyển sang onError// Dừng sau một hành động custom
onComponent: async ({ interaction, pagination }) => {
if (interaction.customId === "confirm") {
await interaction.reply("Đã xác nhận!");
await pagination.stop();
}
}
Cập nhật lại toàn bộ danh sách pages (dữ liệu tĩnh) và render lại pagination
Mảng dữ liệu mới cho từng trang
Promise
Method này dùng để thay thế hoàn toàn dữ liệu hiện tại (pages)
và đồng bộ lại toàn bộ trạng thái pagination.
Nó sẽ:
clearCache)pagestotalPagespage nếu vượt giới hạnreload() để render lại messageDùng khi:
⚠️ Method này chỉ áp dụng cho mode pages (data tĩnh).
Nếu bạn đang dùng pageLoader, nên xử lý logic ở backend hoặc dùng state + reload.
page hiện tại >= totalPages mới
→ tự động set về trang cuối (totalPages - 1)// Sau khi filter dữ liệu
const filtered = allItems.filter(i => i.includes("test"));
await pagination.updatePages(filtered);
// Reset data khi search
pagination.state.keyword = "discord";
const result = await fetchSearchData();
await pagination.updatePages(result);
Khởi tạo một instance PaginationBuilder