Skip to main content

onClick & setCustomId

Hướng dẫn sử dụng onClick()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()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