Skip to main content

@Component

Hướng dẫn sử dụng @Component decorator để xử lý button clicks và các component interactions.

Tổng quan

@Component decorator cho phép bạn xử lý các sự kiện tương tác với components (buttons, selects, etc.) thông qua pattern matching trên button_id.

Cú pháp cơ bản

@Component(options: NezonComponentOptions | string)

Ví dụ đơn giản

import { Injectable } from '@nestjs/common';
import { Component, ComponentPayload, AutoContext, SmartMessage } from '@n0xgg04/nezon';
import type { Nezon } from '@n0xgg04/nezon';

@Injectable()
export class ButtonHandler {
@Component({ pattern: 'click/confirm' })
async onConfirm(
@ComponentPayload() payload: Nezon.ComponentPayload,
@AutoContext() [message]: Nezon.AutoContext,
) {
await message.reply(SmartMessage.text('Confirmed!'));
}
}

Pattern Matching

Exact Match

@Component({ pattern: 'click/confirm' })

Chỉ match với button_id chính xác là 'click/confirm'.

Regex Pattern

@Component({ pattern: '^click/.*' })

Match với mọi button_id bắt đầu bằng 'click/'.

String Short Form

@Component('click/confirm')

Tương đương với @Component({ pattern: 'click/confirm' }).

Named Parameters (RESTful Pattern)

Component hỗ trợ named parameters giống REST API:

@Component({ pattern: '/user/:user_id/:action' })
async onUserAction(
@ComponentParams('user_id') userId: string | undefined,
@ComponentParams('action') action: string | undefined,
@ComponentParams() allParams: Record<string, string> | undefined,
@AutoContext() [message]: Nezon.AutoContext,
) {
console.log('User ID:', userId);
console.log('Action:', action);
console.log('All params:', allParams);
}

Ví dụ button_id: /user/12345/kick

  • userId = '12345'
  • action = 'kick'
  • allParams = { user_id: '12345', action: 'kick' }

Lấy tất cả parameters

@Component({ pattern: '/user/:user_id/:action' })
async onUserAction(
@ComponentParams() params: Record<string, string> | undefined,
@AutoContext() [message]: Nezon.AutoContext,
) {
// params = { user_id: '12345', action: 'kick' }
}

Lấy parameter cụ thể

@Component({ pattern: '/user/:user_id/:action' })
async onUserAction(
@ComponentParam('user_id') userId: string | undefined,
@ComponentParam(0) firstParam: string | undefined, // Lấy theo index
@AutoContext() [message]: Nezon.AutoContext,
) {
// userId = '12345'
// firstParam = '12345' (parameter đầu tiên)
}

Component Payload

Lấy raw payload từ component click:

@Component('click/confirm')
async onConfirm(
@ComponentPayload() payload: Nezon.ComponentPayload,
@AutoContext() [message]: Nezon.AutoContext,
) {
console.log('Button ID:', payload.button_id);
console.log('User ID:', payload.user_id);
console.log('Channel ID:', payload.channel_id);
console.log('Message ID:', payload.message_id);
}

Type:

type ComponentPayload = MessageButtonClicked;
// Bao gồm: button_id, user_id, channel_id, message_id, ...

Component Target

Lấy message gốc (đã được cache) mà không cần fetch lại:

@Component('click/confirm')
async onConfirm(
@ComponentTarget() targetMessage: Nezon.Message | undefined,
@AutoContext() [message]: Nezon.AutoContext,
) {
if (targetMessage) {
// Sử dụng message đã cache
await targetMessage.reply(SmartMessage.text('Confirmed!'));
}
}

Type:

@ComponentTarget(): ParameterDecorator
// Trả về: Nezon.Message | undefined

Ví dụ hoàn chỉnh

Với setCustomId

import { Injectable } from '@nestjs/common';
import {
Command,
Component,
ComponentParams,
AutoContext,
SmartMessage,
ButtonBuilder,
ButtonStyle,
} from '@n0xgg04/nezon';
import type { Nezon } from '@n0xgg04/nezon';

@Injectable()
export class ButtonHandler {
@Command('button')
async onButton(@AutoContext() [message]: Nezon.AutoContext) {
const messageId = message.id ?? 'unknown';
await message.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() [message]: Nezon.AutoContext,
) {
await message.reply(
SmartMessage.text(`Confirmed! Message ID: ${targetId}`)
);
}
}

Với onClick (khuyến nghị)

Xem onClick handlers để biết cách sử dụng onClick thay vì setCustomId.

Type Definitions

interface NezonComponentOptions {
pattern: string; // Pattern để match button_id
id?: string; // Optional: exact ID match
}

type ComponentPayload = MessageButtonClicked;

type ComponentParams = string[] | Record<string, string>;
// Nếu có named parameters: Record<string, string>
// Nếu không: string[]

Best Practices

  1. Sử dụng RESTful pattern cho complex routing

    @Component({ pattern: '/user/:id/:action' })
  2. Sử dụng @ComponentTarget() để tránh fetch lại

    @ComponentTarget() target: Nezon.Message | undefined
  3. Validate parameters trước khi sử dụng

    const userId = params?.user_id;
    if (!userId) {
    await message.reply(SmartMessage.text('Invalid user ID!'));
    return;
    }

API Reference

@Component()

function Component(
options: NezonComponentOptions | string
): MethodDecorator

@ComponentPayload()

function ComponentPayload(): ParameterDecorator
// Trả về: Nezon.ComponentPayload = MessageButtonClicked

@ComponentParams()

function ComponentParams(paramName?: string): ParameterDecorator
// Không có paramName: trả về tất cả params
// Có paramName: trả về param cụ thể
// Trả về: Nezon.ComponentParams = string[] | Record<string, string>

@ComponentParam()

function ComponentParam(positionOrName: number | string): ParameterDecorator
// number: lấy theo index
// string: lấy theo tên (named parameter)
// Trả về: string | undefined

@ComponentTarget()

function ComponentTarget(): ParameterDecorator
// Trả về: Nezon.Message | undefined

Xem thêm