I'm facing a strange problem, I can't disable a button after it's been clicked. Actually, the disable option doesn't appear. For deffing button I use this function
const row = new ActionRowBuilder()
.addComponents(
new ButtonBuilder()
.setCustomId(
)
.setLabel('Test 2')
.setStyle(ButtonStyle.Primary),
new ButtonBuilder()
.setCustomId('test_2')
.setLabel('Test 2')
.setStyle(ButtonStyle.Danger),
);
I am sending this code as a follow up
await interaction.followUp(
{
content: `Test`,
ephemeral: true,
components: [row],
fetchReply: true
}
);
I tried this way too
row[0].components[0].setDisabled(true)
I also tried with foreach.. and the same thing
Should I specify that I use typescript, is it because of this?
CodePudding user response:
When you receive a button interaction, you receive the ActionRow
as the first component of the message (i.e. interaction.message.components[0]
). This contains your buttons inside its component
property.
You could update this row by iterating over this array of buttons and checking if the current interaction
's customId
is the same as the current button's customId
. If it's the same, you will need to use the ButtonBuilder.from()
method to update the button (as Components
received from the API are not directly mutable in v14 of discord.js). Then, you can use .setDisabled(true)
on this.
Once the button is updated, you can edit the original message and send the now updated ActionRow
. You can find an example below:
client.on('messageCreate', (message: Message) => {
if (message.author.bot) return;
const row = new ActionRowBuilder<ButtonBuilder>().addComponents(
new ButtonBuilder()
.setCustomId('test_1')
.setLabel('Test 1')
.setStyle(ButtonStyle.Primary),
new ButtonBuilder()
.setCustomId('test_2')
.setLabel('Test 2')
.setStyle(ButtonStyle.Danger),
);
message.channel.send({ components: [row] });
});
client.on('interactionCreate', async (interaction: Interaction) => {
if (!interaction.isButton()) return;
let { customId } = interaction;
let row = interaction.message.components[0];
// TS complains about components being read-only without "as any"
(row.components as any) = row.components.map((button) =>
button.customId === customId
? ButtonBuilder.from(button as APIButtonComponent).setDisabled(true)
: button,
);
await interaction.message.edit({ components: [row] });
interaction.reply({
content: `Button with ${customId} is disabled`,
ephemeral: true,
});
});