
Drupal 8: Actualizar textfield en formulario con ajax
Autor: fjavimartin
Fecha de Creación: 14/06/2017
Categorías:
Tomando como base el formulario que creamos en nuestro último artículo lo modificaremos para poder actualizar un textfield con el valor de otro mediante ajax.
Recordaréis que partimos de un formulario básico que solamente tiene dos campos (nombre/apellido) y nuestra intención será actualizar el campo apellido cuando modifiquemos el valor del campo nombre.
1. Modificaciones en el formulario
El funcionamiento de ajax es exactamente el mismo que con javascript/jquery/.. o cualquier otra tecnología, con al particularidad que el único selector que podemos utilizar es el del “id” del elemento donde se alojará la respuesta de ajax. Es por esto que nuestra primera modificación será añadir un prefix/suffix al campo apellido que será donde alojaremos la respuesta de ajax:
$form['apellido'] = [
'#type' => 'textfield',
'#title' => $this->t('Apellidos'),
'#description' => $this->t('Introduce los apellidos'),
'#prefix' => '<div id="field-apellido">',
'#suffix' => '</div>',
];
De esta manera el html generado será:
<div id="field-apellido"><div class="form-item js-form-item form-type-textfield js-form-type-textfield form-item-apellido js-form-item-apellido form-group">
<label for="edit-apellido" class="control-label">Apellidos</label>
<input data-drupal-selector="edit-apellido" class="form-text form-control" type="text" id="edit-apellido" name="apellido" value="" size="60" maxlength="128" title="" data-toggle="tooltip" data-original-title="Introduce los apellidos">
</div>
</div>
Nuestra siguiente modificación será añadir al campo nombre la función ajax que se lanzará cuando pierda el foco:
$form['nombre'] = [
'#type' => 'textfield',
'#title' => $this->t('Nombre'),
'#description' => $this->t('Introduce un nombre'),
'#ajax' => [
'callback' => [$this, 'ajaxApellido'],
'wrapper' => 'field-apellido',
'disable-refocus' => true,
],
];
Mediante la entrada ajax definimos el comportamiento del elemento:
Callback: Informamos de la función que se ejecutará cuando se lance el evento que dispara ajax. En nuestro caso será una función que definiremos más adelante en nuestra clase BasicForm. En la documentación de drupal podréis leer que también se puede utilizar el valor ‘::ajaxApellido’ para indicar que la función está en la propia clase, pero a mi no me ha funcionado correctamente. También podéis llamar a la función de cualquier otra clase indicando el nombre completo ‘Drupal\equipos_form\Form\BasicForm::ajaxApellido’.
Wrapper: Será el valor de la propiedad id del elemento donde se guardará el resultado de la función Ajax.
Disable-refocus: Cuando un elemento en un formulario de drupal tiene definida la propiedad ajax, por defecto, cada vez que pierde el foco y se ejecuta la correspondiente función ajax, vuelve a recuperar el foco impidiendo que pueda pasar a otro elemento. Solamente mediante la propiedad disable-refocus podemos impedir este comportamiento haciendo que el foco pueda pasar al siguiente elemento. A mi entender este comportamiento es erróneo y no deberíamos de tener que utilizar esta propiedad, pero………..como dicen en mi pueblo: ‘Doctores tiene la Santa Madre Iglesia’.
2. Función Ajax
El último paso será añadir la función que nos devuelva el campo apellido modificado.
public function ajaxApellido(array &$form, FormStateInterface $form_state) {
$nombre = $form_state->getValue('nombre');
if (strtolower($nombre) == 'javier') {
$form['apellido']['#value'] = 'Martín';
}
return $form['apellido'];
}
La función es muy simple, pero nos sirve para ver como funciona ajax en drupal. Recibe dos parámetros, el primero de ellos con el formulario que estamos utilizando y el segundo con el estado actual del formulario.
Como podéis ver, sobre el formulario que recibimos como parámetro modifico el valor del campo apellido y devuelvo solamente este elemento. Es fundamental hacerlo así, puesto que si creáramos un elemento nuevo, este no estaría recogido dentro del formulario original y no podríamos recoger el valor del campo cuando hiciéramos el submit del mismo.
Si tenéis curiosidad y lo hacéis, al enviar el formulario recibiréis un magnífico aviso de “Apellido vacío” procedente de la función de validación.
3. Conclusiones
Este pequeño ejemplo nos ha servido para ver el funcionamiento completo de ajax con las opciones básicas, pero podemos utilizar muchas más propiedades para [‘#ajax’]:
‘event’ => ‘keyup’ → Podemos utilizar cualquier evento de los definidos en javascript para lanzar un evento ajax.
$form_state→getTriggeringElement() nos devolverá el elemento que ha lanzado el evento ajax.
Para este ejemplo hemos optado por devolver el array renderizable con el resultado de la función, pero también podemos devolver una secuencia de comandos ajax (relación completa en Ajax Api de drupal) como la siguiente:
$response = new AjaxResponse();
$response->addCommand(new ReplaceCommand(
'#edit-date-format-suffix',
'<small id="edit-date-format-suffix">' . $format . '</small>'));
Podremos implementar ajax en cualquier enlace simplemente con añadir la clase ‘use-ajax’ o ‘use-ajax-submit’ en un botón de envío.
Recursos
http://www.e-quipos.es/blog/drupal-8-creaci%C3%B3n-de-formularios
https://api.drupal.org/api/drupal/core!core.api.php/group/ajax/8.2.x