Manual:HTMLForm (Tutorial 2)
El resto de esta página trata sobre el uso de HTMLForm a través de entradas genéricas $formDescriptor
(configuraciones que son comunes a todos los tipos de campos).
Estamos por tanto trabajando solo en entradas HTMLTextField.
Saltar la parte genérica e ir directamente a la parte de especificación de los campos
Aquí estamos en /mediawiki/extensions/MyForm/MyForm_body.php
y trabajando en la función execute()
...
Punto de partida
public function execute( $par ) {
$this->setHeaders();
$this->getOutput()->addHTML( 'Hello World' );
}
Añadir un campo simple de texto
Reemplacemos «Hello World» por un campo de texto denominado simpletextfield
public function execute( $par ) {
$this->setHeaders();
// Vector formDescriptor para indicar a HTMLForm qué construir
$formDescriptor = [
'simpletextfield' => [
'label' => 'Simple Text Field', // Label of the field
'class' => 'HTMLTextField', // Input type
]
];
// Construye el objeto HTMLForm
$htmlForm = HTMLForm::factory( 'table', $formDescriptor, $this->getContext() );
// Texto que mostrar en el botón de enviar
$htmlForm->setSubmitText( 'Allons-y gaiement' );
$htmlForm->show(); // Muestra el formulario
}
Ahora el formulario tiene este aspecto:
Añadir una retrollamada
Desgraciadamente, el código anterior muestra el formulario, pero el formulario no funciona. ¡Tenemos que escribir algo de lógica para procesar la entrada del formulario!
public function execute( $par ) {
$this->setHeaders();
// Vector formDescriptor para indicar a HTMLForm qué construir
$formDescriptor = [
'simpletextfield' => [
'label' => 'Simple Text Field', // Label of the field
'class' => 'HTMLTextField', // Input type
]
];
// Construye el objeto HTMLForm con el nombre de formulario 'myform'
$htmlForm = new HTMLForm( $formDescriptor, $this->getContext(), 'myform' );
// Texto que mostrar en el botón de enviar
$htmlForm->setSubmitText( 'Allons-y gaiement' );
// Establecemos una función de retrollamada
$htmlForm->setSubmitCallback( [ $this, 'processInput' ] );
// Llama a processInput() en tu clase que extiende SpecialPage al enviar
// Muestra el formulario
$htmlForm->show();
}
// Función de retrollamada
// Retrollamada al pulsar en enviar, aquí hacemos toda la lógica que queremos implementar…
public static function processInput( $formData ) {
// Si se devuelve 'true', no se volverá a mostrar el formulario
if ( $formData['simpletextfield'] === 'next' ) {
return true;
} elseif ( $formData[ 'simpletextfield' ] === 'again' ) {
// Si se devuelve 'false', se volverá a mostrar el formulario
return false;
}
// Si se devuelve una cadena, se mostrará en forma de mensaje de error con el formulario
return 'Try again';
}
Ahora, el formulario procesa los datos enviados:
Método de envío
El formulario se puede configurar para utilizar ya sea el método de envío POST o GET.
- POST (predeterminado): El contenido de los campos del formulario no se muestra en la URL de la página. Este método debería utilizarse para formularios que cambien el contenido del wiki (por ejemplo, editar páginas o bloquear usuarios).
- GET: El contenido de los campos del formulario se muestra en la URL de la página. La URL resultante se puede guardar como marcador o enlazar para permitir que otros accedan a ella. Sin embargo, el envío de formularios muy largos (con varios kilobytes de texto) puede fallar. Este método debería utilizarse para formularios que no cambien el contenido del wiki (por ejemplo, mostrar una lista de páginas).
Si tratas de enviar los datos mediante una solicitud GET, tendrás que añadir lo siguiente:
$htmlForm->setMethod( 'get' );
Nótese que los formularios GET que utilicen un campo check
o multiselect
deben tener un «identificador de formulario» para funcionar correctamente, al igual que si estabas utilizando varios formularios en una página – véase Utilizar varios formularios en una sola página más adelante.
Añadir validación
Los campos se pueden validar individualmente antes de ejecutar la función de retrollamada.
Primero se lo indicamos a HTMLForm añadiendo esta línea:
// Llama a validateSimpteTextField() en tu clase que extiende SpecialPage
'validation-callback' => [ $this, 'validateSimpleTextField' ],
en formDescriptor
:
// Vector formDescriptor para indicar a HTMLForm qué construir
$formDescriptor = [
'simpletextfield' => [
// Etiqueta del campo
'label' => 'Simple Text Field',
'class' => 'HTMLTextField',
// Llama a validateSimpteTextField() en tu clase que extiende SpecialPage
'validation-callback' => [ $this, 'validateSimpleTextField' ],
]
];
Entonces escribimos la lógica de validación:
public static function validateSimpleTextField( $simpleTextField, $allData ) {
if ( $simpleTextField === 'merde' ) {
return 'Excuse my French';
}
return true;
}
Ahora, la lógica de validación verifica los datos enviados antes de procesarlos:
Campo obligatorio
Puedes especificar que un campo es obligatorio sin más que añadir
'required' => true,
al formDescriptor. Cualquier validation-callback sobreescribirá 'required'. Si necesitas validar un campo obligatorio, añade la siguiente lógica a tu función de validación por retrollamada:
if ( $simpleTextField === '' ) {
return wfMessage( 'htmlform-required', 'parseinline' );
}
Añadir filtros
El filtrado se produce ANTES de la validación para cambiar la entrada.
Declaración correspondiente en formDescriptor:
'filter-callback' => [ $this, 'filterSimpleTextField' ],
Lógica de filtrado:
public static function filterSimpleTextField( $simpleTextField, $allData ) {
// Añadir '?!?' a la entrada
return $simpleTextField . '?!?';
}
Añadir soporte de internacionalización (i18n)
Esta funcionalidad permite traducir la etiqueta al idioma definido en las preferencias de la interfaz del usuario. Basta con reemplazar 'label' por 'label-message' en formDescriptor para obtener automáticamente la cadena a través de la rutina i18n:
$formDescriptor = [
'simpletextfield' => [
// Identificador del mensaje i18n para la etiqueta del campo
'label-message' => 'myform-simpletextfield',
// Tipo de entrada
'class' => 'HTMLTextField',
'validation-callback' => [ $this, 'validateSimpleTextField' ],
'filter-callback' => [ $this, 'filterSimpleTextField' ],
]
];
No olvides añadir la entrada correcta en los archivos de localización. Por ejemplo, aquí, en inglés y francés:
"myform-simpletextfield": "International Simple Text Field"
"myform-simpletextfield": "Champ de texte simple international"
Para el botón de enviar, tenemos que hacerlo «manualmente»:
$htmlForm->setSubmitText( wfMessage( 'myform-submit' ) );
Por supuesto, como siempre, tendrás que añadir la entrada myform-submit en los archivos de localización.
Añadir secciones
Ahora tendremos que añadir algunos campos y organizarlos, así que cambiemoos a un formDescriptor de mayor tamaño.
$formDescriptor = [
'field1' => [
'section' => 'section1',
'class' => 'HTMLTextField',
'label' => 'field1',
],
'field2' => [
'section' => 'section1',
'class' => 'HTMLTextField',
'label' => 'field1',
],
'field3' => [
'section' => 'section2',
'class' => 'HTMLTextField',
'label' => 'field1',
],
'field4' => [
'section' => 'section3',
'class' => 'HTMLTextField',
'label' => 'field1',
]
];
La cadena de sección mostrada se extrae automáticamente de los archivos de localización. Aquí, por tanto, tenemos que añadir esto a en.json:
{
"section1": "The First Section",
"section2": "Section II",
"section3": "Third Section"
}
Ahora el formulario tiene este aspecto:
Subsecciones
Las secciones se pueden anidar fácilmente con el increíble poder de /.
$formDescriptor = [
'field1' => [
'section' => 'section1',
'class' => 'HTMLTextField',
'label' => 'field1',
],
'field2' => [
'section' => 'section1/subsectionA',
'class' => 'HTMLTextField',
'label' => 'field1',
],
'field3' => [
'section' => 'section2/subsectionB',
'class' => 'HTMLTextField',
'label' => 'field1',
],
'field4' => [
'section' => 'section2/subsectionC',
'class' => 'HTMLTextField',
'label' => 'field1',
]
];
Los identificadores de i18n tendrán esta forma:
'subsectionA'
Ahora, el formulario tiene este aspecto:
Añadir texto de ayuda
¿Qué piensas sobre brindarles a los usuarios unas instrucciones para utilizar tu formulario con facilidad?
help
o help-message
(un nombre de mensaje i18n) están aquí para ti.
$formDescriptor = [
'field1' => [
'section' => 'section1',
'class' => 'HTMLTextField',
'label' => 'field1',
'help' => 'Just say something!',
],
];
Ahora el formulario tiene este aspecto:
Añadir CLASS e ID HTML
cssclass
y id
están aquí para ti.
$formDescriptor = [
'field1' => [
'section' => 'section1',
'class' => 'HTMLTextField',
'label' => 'field1',
// Añade a la clase del objeto contenedor
'cssclass' => 'AClassForField1',
// Añade al objeto de entrada
'id' => 'AnIdForField1',
],
];
Cambiar el nombre de la entrada
Por defecto, el nombre de la entrada es wp{$fieldname}
; para el ejemplo anterior, el nombre de la entrada es por tanto wpfield1
. Esto se puede cambiar con name
:
$formDescriptor = [
'field1' => [
'section' => 'section1',
'class' => 'HTMLTextField',
'label' => 'field1',
'cssclass' => 'AClassForField1',
'id' => 'AnIdForField1',
'name' => 'ANameForField1',
],
];
Simplemente para darte una idea, he aquí la salida HTML generada:
<tr class="mw-htmlform-field-HTMLTextField AClassForField1">
<td class="mw-label">
<label for="AnIdForField1">field1</label>
</td>
<td class="mw-input">
<input id="AnIdForField1" size="45" name="ANameForField1">
</td>
</tr>
Deshabilitar la entrada
disabled está presente y el usuario no puede modificar la entrada. (En algunos navegadores puede que no sea posible copiar el valor.) El elemento no se enviará al servidor.
'disabled' => true,
¡Tan simple como eso!
Hacer que una entrada sea de solo lectura
readonly está presente, y el usuario no puede modificar la entrada. El elemento se enviará al servidor.
'readonly' => true,
De nuevo, ¡tan simple como eso!
Utilizar varios formularios en una sola página
Versión de MediaWiki: | ≥ 1.28 |
Si utilizas varios formularios en una sola página especial (por ejemplo, uno para mostrar resultados de búsqueda y otro para modificar un resultado), tienes que establecer un «identificador de formulario» para permitir que HTMLForm detecte cuál de los formularios se está enviando. El identificador puede ser cualquier cadena, y debe ser diferente para cada formulario.
$htmlForm->setFormIdentifier( 'myform1' );
Por motivos técnicos, esto también es necesario a la hora de utilizar un campo check
o multiselect
en un formulario GET; de otra manera, HTML no podrá detectar qué formulario se ha enviado y por tanto si debe cargar los valores predeterminados o no.[1]