New component under a PaginatedMessage
Hello ! I want to add a new component under my PagniatedMessage. This PaginatedMessage is a list embed that represents entities of a model. The user is invited to chose a row to edit via a select menu under the embed. The select menu is successfully added when the embed shows but disapear when I change page. I would like to know how to make my dropdown list refresh on every page change, is there a listener or something like that that can handle this?
Here is the code of the listEntities method :
Thank you for your help ! Have a great day !
protected async listEntities(interaction: CommandInteraction<CacheType>, page: number) {
try {
//creting a modelInstance with the redis basemodel
const ModelInstance = await this.Model;
//get all the entities (rows) in the table
const entities = await ModelInstance.getAll();
if (entities.length === 0) {
await interaction.reply({ content: `Aucune ${this.entityName} n'est enregistrée.`, ephemeral: true });
return;
}
const itemsPerPage = 10; // maximum items per page
const uniqueId = Date.now(); // Unique ID variable
const selectMenu = new StringSelectMenuBuilder() // Select menu for chosing an entity
.setCustomId(`select_entity_${uniqueId}`)
.setPlaceholder('Sélectionner un élément pour plus d\'options')
.addOptions(entities.map(entity => ({
label: entity.name || entity.label,
value: entity.id
})));
const selectRow = new ActionRowBuilder<StringSelectMenuBuilder>()
.addComponents(selectMenu);
const paginatedMessage = new PaginatedMessage(); //The paginated message
for (let i = 0; i < entities.length; i += itemsPerPage) { //Insertion
const paginatedItems = entities.slice(i, i + itemsPerPage);
const description = paginatedItems
.map((entity, index) => `${i + index + 1}. ${entity.name || entity.label}`)
.join('\n');
paginatedMessage.addPage({
embeds: [
new EmbedBuilder()
.setTitle(`Liste des ${this.entityName}s (Page ${(i / itemsPerPage) + 1})`)
.setColor('#0099ff')
.setDescription(description)
]
});
}
await paginatedMessage.run(interaction);
// Fetch current components (buttons) and add selectRow without replacing them
const message = await interaction.fetchReply();
const currentComponents = message.components ? [...message.components] : [];
currentComponents.push(selectRow); // Add the select menu to existing components
await interaction.editReply({
components: currentComponents
});
const selectCollector = interaction.channel?.createMessageComponentCollector({
componentType: ComponentType.StringSelect,
time: 60000,
filter: (i) => i.customId === `select_entity_${uniqueId}` && i.user.id === interaction.user.id,
});
selectCollector?.on('collect', async (i) => {
if (i.user.id !== interaction.user.id) {
await i.reply({ content: 'Vous ne pouvez pas utiliser cette sélection.', ephemeral: true });
return;
}
await this.showEntityDetails(i, i.values[0]);
});
} catch (error) {
console.error(`Erreur lors de la récupération des ${this.entityName}s:`, error);
await interaction.reply({ content: `Impossible de lister les ${this.entityName}s.`, ephemeral: true });
}
}
protected async listEntities(interaction: CommandInteraction<CacheType>, page: number) {
try {
//creting a modelInstance with the redis basemodel
const ModelInstance = await this.Model;
//get all the entities (rows) in the table
const entities = await ModelInstance.getAll();
if (entities.length === 0) {
await interaction.reply({ content: `Aucune ${this.entityName} n'est enregistrée.`, ephemeral: true });
return;
}
const itemsPerPage = 10; // maximum items per page
const uniqueId = Date.now(); // Unique ID variable
const selectMenu = new StringSelectMenuBuilder() // Select menu for chosing an entity
.setCustomId(`select_entity_${uniqueId}`)
.setPlaceholder('Sélectionner un élément pour plus d\'options')
.addOptions(entities.map(entity => ({
label: entity.name || entity.label,
value: entity.id
})));
const selectRow = new ActionRowBuilder<StringSelectMenuBuilder>()
.addComponents(selectMenu);
const paginatedMessage = new PaginatedMessage(); //The paginated message
for (let i = 0; i < entities.length; i += itemsPerPage) { //Insertion
const paginatedItems = entities.slice(i, i + itemsPerPage);
const description = paginatedItems
.map((entity, index) => `${i + index + 1}. ${entity.name || entity.label}`)
.join('\n');
paginatedMessage.addPage({
embeds: [
new EmbedBuilder()
.setTitle(`Liste des ${this.entityName}s (Page ${(i / itemsPerPage) + 1})`)
.setColor('#0099ff')
.setDescription(description)
]
});
}
await paginatedMessage.run(interaction);
// Fetch current components (buttons) and add selectRow without replacing them
const message = await interaction.fetchReply();
const currentComponents = message.components ? [...message.components] : [];
currentComponents.push(selectRow); // Add the select menu to existing components
await interaction.editReply({
components: currentComponents
});
const selectCollector = interaction.channel?.createMessageComponentCollector({
componentType: ComponentType.StringSelect,
time: 60000,
filter: (i) => i.customId === `select_entity_${uniqueId}` && i.user.id === interaction.user.id,
});
selectCollector?.on('collect', async (i) => {
if (i.user.id !== interaction.user.id) {
await i.reply({ content: 'Vous ne pouvez pas utiliser cette sélection.', ephemeral: true });
return;
}
await this.showEntityDetails(i, i.values[0]);
});
} catch (error) {
console.error(`Erreur lors de la récupération des ${this.entityName}s:`, error);
await interaction.reply({ content: `Impossible de lister les ${this.entityName}s.`, ephemeral: true });
}
}
5 Replies