Modales

Con los modales (modals) puedes crear formularios emergentes que permiten a los usuarios proporcionar entradas formateadas a través de envíos. Cubriremos cómo crear, mostrar y recibir formularios modales utilizando discord.js.

CONSEJO

Esta página es un seguimiento de la sección de interacciones (comandos de barra). Por favor, lee atentamente esa sección primero para que puedas comprender los métodos utilizados en esta sección.

Construyendo y respondiendo con modales

A diferencia de los componentes de mensaje, los modales no son estrictamente componentes en sí mismos. Son una estructura de devolución de llamada (callback) utilizada para responder a las interacciones.

CONSEJO

Puedes tener un máximo de cinco ActionRowBuilderopen in new window por constructor de modales y un TextInputBuilderopen in new window dentro de un ActionRowBuilderopen in new window. Actualmente, no puedes usar StringSelectMenuBuilderopen in new window p ButtonBuilderopen in new window en los contenedores de componentes de los modales.

Para crear un modal, crea un nuevo ModalBuilderopen in new window. Luego puedes usar los métodos "setters" para agregar el ID personalizado (custom_id) y el título (title).

const { Events, ModalBuilder } = require('discord.js');

client.on(Events.InteractionCreate, async interaction => {
	if (!interaction.isChatInputCommand()) return;

	if (interaction.commandName === 'ping') {
		const modal = new ModalBuilder()
			.setCustomId('miModal')
			.setTitle('Mi Modal');

		// TODO: Agregar componentes al modal...
	}
});
 





 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13

CONSEJO

La id personalizada (custom_id) es una string definida por ti de hasta 100 caracteres. Utiliza este campo para asegurarte de que puedas definir de forma única todas las interacciones procedentes de tus modales.

El siguiente paso es agregar los campos de entrada en los cuales los usuarios pueden ingresar texto libremente al responder. Agregar los campos de entrada es similar a agregar componentes a los mensajes.

Al final, llamamos a ChatInputCommandInteraction#showModalopen in new window para mostrar el modal al usuario.

ADVERTENCIA

Si estás utilizando TypeScript, deberás especificar el tipo de componentes que contiene tu contenedor de componentes. Esto se puede hacer especificando el parámetro genérico en ActionRowBuilderopen in new window.

- new ActionRowBuilder()
+ new ActionRowBuilder<ModalActionRowComponentBuilder>()
1
2
const { ActionRowBuilder, Events, ModalBuilder, TextInputBuilder, TextInputStyle } = require('discord.js');

client.on(Events.InteractionCreate, async interaction => {
	if (!interaction.isChatInputCommand()) return;

	if (interaction.commandName === 'ping') {
		// Crear el modal
		const modal = new ModalBuilder()
			.setCustomId('miModal')
			.setTitle('Mi Modal');

		// Añadir componentes al modal

		// Crear los componentes de entrada de texto
		const favoriteColorInput = new TextInputBuilder()
			.setCustomId('entradaColorFavorito')
		    // La etiqueta es el indicador que el usuario ve para esta entrada
			.setLabel("What's your favorite color?")
		    // Corto significa una sola línea de texto
			.setStyle(TextInputStyle.Short);

		const hobbiesInput = new TextInputBuilder()
			.setCustomId('entradaPasatiempos')
			.setLabel('¿Cuáles son tus aficiones favoritas?')
		    // Párrafo significa varias líneas de texto.
			.setStyle(TextInputStyle.Paragraph);

		// Un contenedor de componentes solo contiene una entrada de texto,
		// por lo que necesita un contenedor de componentes por cada entrada de texto.
		const firstActionRow = new ActionRowBuilder().addComponents(favoriteColorInput);
		const secondActionRow = new ActionRowBuilder().addComponents(hobbiesInput);

		// Añadir entradas al modal
		modal.addComponents(firstActionRow, secondActionRow);

		// Mostrar el modal al usuario
		await interaction.showModal(modal);
	}
});
 










 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

Reinicia tu bot y vuelve a utilizar el comando /ping. Deberías ver un formulario emergente parecido a la imagen de abajo:

ADVERTENCIA

Mostrar un modal debe ser la primera respuesta a una interacción. No se puede defer() o deferUpdate() y mostrar un modal más tarde.

Estilos de entrada

Actualmente hay dos estilos de entrada disponibles::

  • Short, una entrada de texto de una sola línea;
  • Paragraph, una entrada de texto de varias líneas similar a la etiqueta HTML <textarea>;

Propiedades de entradas

Además del customId, label y style, una entrada de texto puede personalizarse de varias formas para aplicar validación, preguntar al usuario o establecer valores por defecto a través de los métodos TextInputBuilderopen in new window:

const input = new TextInputBuilder()
	// establece el número máximo de caracteres permitidos
	.setMaxLength(1000)
	// establece el número mínimo de caracteres necesarios para el envío
	.setMinLength(10)
	// establece un marcador de posición de cadena para preguntar al usuario
	.setPlaceholder('¡Ingresa un texto!')
	// establecer un valor por defecto para pre-llenar la entrada
	.setValue('Predeterminado')
	// requiere un valor en este campo de entrada
	.setRequired(true);
1
2
3
4
5
6
7
8
9
10
11

Recibiendo envíos de modales

Colectores de interacciones

Los envíos de modales se pueden recopilar dentro del ámbito de la interacción que los mostró utilizando un InteractionCollectoropen in new window, o el método ChatInputCommandInteraction#awaitModalSubmitopen in new window a modo de promesa. Ambos proporcionan instancias de la clase ModalSubmitInteractionopen in new window como elementos recogidos.

Para obtener una guía detallada sobre la recepción de componentes de mensajes a través de recopiladores, consulte la guía de recopiladores.

El evento interactionCreate

Para recibir un evento ModalSubmitInteractionopen in new window, adjunta un receptor de eventos Client#event:interactionCreateopen in new window a su cliente y usa la protección de tipado BaseInteraction#isModalSubmitopen in new window para asegurarte de que solo recibe modales:

client.on(Events.InteractionCreate, interaction => {
	if (!interaction.isModalSubmit()) return;
	console.log(interaction);
});
 


 
1
2
3
4

Responder a los envíos de modales

La clase ModalSubmitInteractionopen in new window proporciona los mismos métodos que la clase ChatInputCommandInteractionopen in new window. Estos métodos se comportan igual:

  • reply()
  • editReply()
  • deferReply()
  • fetchReply()
  • deleteReply()
  • followUp()

Si el modal se mostró desde un ButtonInteractionopen in new window o StringSelectMenuInteractionopen in new window, también proporcionará estos métodos, que se comportan igual:

  • update()
  • deferUpdate()
client.on(Events.InteractionCreate, async interaction => {
	if (!interaction.isModalSubmit()) return;
	if (interaction.customId === 'miModal') {
		await interaction.reply({ content: '¡Tu envío se ha recibido correctamente!' });
	}
});
 

 
 
 

1
2
3
4
5
6

CONSEJO

Si estás usando typescript, puedes usar la protección de tipado ModalSubmitInteraction#isFromMessageopen in new window, para asegurarte de que la interacción recibida proviene de un MessageComponentInteraction.

Extrayendo datos desde un modal recibido

Lo más probable es que necesites leer los datos enviados por el usuario en el modal. Puedes hacerlo accediendo al ModalSubmitInteraction#fieldsopen in new window. Desde ahí puedes llamar a ModalSubmitFields#getTextInputValueopen in new window con el id personalizado de la entrada de texto para obtener el valor.

client.on(Events.InteractionCreate, interaction => {
	if (!interaction.isModalSubmit()) return;

	// Obtener los datos introducidos por el usuario
	const favoriteColor = interaction.fields.getTextInputValue('entradaColorFavorito');
	const hobbies = interaction.fields.getTextInputValue('entradaPasatiempos');
	console.log({ favoriteColor, hobbies });
});




 
 
 

1
2
3
4
5
6
7
8