Skip to main content

onClick & setCustomId

Hướng dẫn sử dụng onClick() và setCustomId() trong ButtonBuilder để xử lý button clicks.

Tổng quan​

ButtonBuilder cung cấp hai cách để xử lý button clicks:

  1. setCustomId() - Set custom ID và xử lý bằng @Component decorator
  2. onClick() - Inline handler tự động đăng ký (khuyến nghị)

Button Example

setCustomId()​

Set custom ID cho button và xử lý bằng @Component decorator.

Cú pháp​

setCustomId(customId: string): ButtonBuilder

Ví dụ​

import { Command, AutoContext, SmartMessage, ButtonBuilder, ButtonStyle } from '@n0xgg04/nezon';
import type { Nezon } from '@n0xgg04/nezon';

@Command('button')
async onButton(@AutoContext() [managedMessage]: Nezon.AutoContext) {
await managedMessage.reply(
SmartMessage.text('Click the button!')
.addButton(
new ButtonBuilder()
.setCustomId('click/confirm')
.setLabel('Confirm')
.setStyle(ButtonStyle.Success)
)
);
}

@Component({ pattern: 'click/confirm' })
async onConfirm(@AutoContext() [managedMessage]: Nezon.AutoContext) {
await managedMessage.reply(SmartMessage.text('Confirmed!'));
}

Với Named Parameters​

@Command('button')
async onButton(@AutoContext() [managedMessage]: Nezon.AutoContext) {
const messageId = managedMessage.id ?? 'unknown';
await managedMessage.reply(
SmartMessage.text('Click the button!')
.addButton(
new ButtonBuilder()
.setCustomId(`/demo/success/${messageId}`)
.setLabel('Confirm')
.setStyle(ButtonStyle.Success)
)
);
}

@Component({ pattern: '/demo/success/:message_id' })
async onConfirm(
@ComponentParams('message_id') targetId: string | undefined,
@AutoContext() [managedMessage]: Nezon.AutoContext,
) {
await managedMessage.reply(SmartMessage.text(`Confirmed! ID: ${targetId}`));
}

Type​

setCustomId(customId: string): ButtonBuilder
// Throws error nếu onClick() đã được set

onClick() (Khuyến nghị)​

Set inline click handler, tự động generate ID và đăng ký handler.

Cú pháp​

onClick(handler: ButtonClickHandler): ButtonBuilder

Ví dụ cơ bản​

import { Command, AutoContext, SmartMessage, ButtonBuilder, ButtonStyle } from '@n0xgg04/nezon';
import type { Nezon } from '@n0xgg04/nezon';

@Command('button')
async onButton(@AutoContext() [managedMessage]: Nezon.AutoContext) {
await managedMessage.reply(
SmartMessage.text('Click the button!')
.addButton(
new ButtonBuilder()
.setLabel('Click Me')
.setStyle(ButtonStyle.Primary)
.onClick(async (context) => {
await context.message.reply(SmartMessage.text('Button clicked!'));
})
)
);
}

ButtonClickContext​

Handler nhận ButtonClickContext với các entities đã được resolve sẵn:

interface ButtonClickContext {
message: ManagedMessage; // ✅ Đã resolve
channel: TextChannel | undefined; // ✅ Đã resolve
user: User | undefined; // ✅ Đã resolve
clan: Clan | undefined; // ✅ Đã resolve
client: MezonClient; // ✅ Đã resolve
}

Ví dụ với Context​

@Command('button')
async onButton(@AutoContext() [managedMessage]: Nezon.AutoContext) {
await managedMessage.reply(
SmartMessage.text('Click the button!')
.addButton(
new ButtonBuilder()
.setLabel('Get Info')
.setStyle(ButtonStyle.Info)
.onClick(async ({ message, channel, user, clan }) => {
const channelName = channel?.name ?? 'unknown';
const userName = user?.username ?? 'unknown';
const clanName = clan?.name ?? 'unknown';

await message.reply(
SmartMessage.text(
`User: ${userName}\nChannel: ${channelName}\nClan: ${clanName}`
)
);
})
)
);
}

Nhiều Buttons với onClick​

@Command('menu')
async onMenu(@AutoContext() [managedMessage]: Nezon.AutoContext) {
await managedMessage.reply(
SmartMessage.text('Choose an option:')
.addButton(
new ButtonBuilder()
.setLabel('Option 1')
.setStyle(ButtonStyle.Primary)
.onClick(async (context) => {
await context.message.reply(SmartMessage.text('Option 1 selected!'));
})
)
.addButton(
new ButtonBuilder()
.setLabel('Option 2')
.setStyle(ButtonStyle.Success)
.onClick(async (context) => {
await context.message.reply(SmartMessage.text('Option 2 selected!'));
})
)
.addButton(
new ButtonBuilder()
.setLabel('Option 3')
.setStyle(ButtonStyle.Danger)
.onClick(async (context) => {
await context.message.reply(SmartMessage.text('Option 3 selected!'));
})
)
);
}

So sánh setCustomId vs onClick​

Tính năngsetCustomIdonClick
ID generationManualAuto (UUID)
Handler locationSeparate @ComponentInline
Context resolutionManualAuto
Type safetyGoodExcellent
Code organizationScatteredCo-located
Recommended❌✅

Validation​

ButtonBuilder không cho phép dùng cả setCustomId() và onClick() cùng lúc:

// ❌ Sẽ throw error
new ButtonBuilder()
.setCustomId('click/confirm')
.onClick(async () => {}) // Error!

// ❌ Sẽ throw error
new ButtonBuilder()
.onClick(async () => {})
.setCustomId('click/confirm') // Error!

Type Definitions​

type ButtonClickHandler = (
context: ButtonClickContext
) => Promise<void> | void;

interface ButtonClickContext {
message: ManagedMessage;
channel: TextChannel | undefined;
user: User | undefined;
clan: Clan | undefined;
client: MezonClient;
}

Best Practices​

  1. Ưu tiên sử dụng onClick()

    .onClick(async (context) => {
    // Handler code
    })
  2. Sử dụng context đã resolve

    .onClick(async ({ message, channel, user }) => {
    // Không cần fetch lại
    })
  3. Sử dụng setCustomId() khi cần pattern matching

    .setCustomId('/user/:id/:action')
    // Với @Component({ pattern: '/user/:id/:action' })

API Reference​

setCustomId()​

setCustomId(customId: string): ButtonBuilder
// Throws: Error nếu onClick() đã được set

onClick()​

onClick(handler: ButtonClickHandler): ButtonBuilder
// Throws: Error nếu setCustomId() đã được set
// Auto-generates: Unique ID với crypto.randomUUID()

Xem thêm​