Cómo crear un Formulario Multi Step en Drupal 8

Author Top
enzo

El último fin de semana organize y participe en la iniciativa  Global Sprint Weekend  de la Comunidad Drupal  con una sede en Costa Rica.

Entre charlas y contribuciones encontré una solicitud interesante en Drupal 8 y quiero compartir la implementación.

Quiero crear un formulario Multi Step, debido a que  Drupal 8 aun no tiene una versión, hay muchas cosas que fácilmente hacemos en Drupal 7, pero ahora de alguna manera  tenemos que  aprender de nuevo cómo resolver nuestros problemas de una manera diferente o usando un nuevo estilo el estilo Drupal/Symfony.

Voy a crear un formulario Multi Step para que los usuarios puedan encontrar un coche proporcionando Año, Estilo y rendimiento de la gasolina.

1. Crear modulo

Voy a omitir la explicación acerca de cómo crear el módulo multi_step_form en Drupal 8, porque se puede generar con el proyecto Drupal console ejecutando el siguiente comando.

$ drupal generate:module

Después de generar el módulo vamos a utilizar otro comando para agregar un formulario con las propiedades requeridas como se puede ver a continuación

$ drupal generate:form:config

Como resultado obtendremos un formulario con un método buildForm como este

/**
 * {@inheritdoc}
 */
public function buildForm(array $form, FormStateInterface $form_state) {

  $config = $this->config('multi_step.multi_step_form_config');

  $form['model'] = [
    '#type' => 'select',
    '#title' => $this->t('Model'),
    '#description' => $this->t(''),
          '#options' => array('1997', '1998', '1999', '2000', '2001', '2002', '2003', '2004', '2005', '2006', '2007', '2008', '2009', '2010', '2011', '2012', '2013', '2014', '2015'),
          '#default_value' => $config->get('model'),
  ];

  $form['body_style'] = [
    '#type' => 'checkboxes',
    '#title' => $this->t('Body Style'),
    '#description' => $this->t(''),
          '#options' => array('Coupe', 'Sedan', 'Convertible', 'Hatchbac', 'Station wagon', 'SUV', 'Minivan', 'Full-size van', 'Pick-up'),
          '#default_value' => $config->get('body_style'),
  ];

  $form['gas_mileage'] = [
    '#type' => 'radios',
    '#title' => $this->t('Gas Mileage'),
    '#description' => $this->t(''),
          '#options' => array('20 mpg or less', '21 mpg or more', '26 mpg or more', '31 mpg or more', '36 mpg or more', '41 mpg or more'),
          '#default_value' => $config->get('gas_mileage'),
  ];

  return parent::buildForm($form, $form_state);

}

1.1 Definir propiedad Step

Dentro de la clase Form necesitamos una propiedad protegida para almacenar el step actual de Multi Step, como se muestra en  el siguiente fragmento de código.

class MultiStepForm extends ConfigFormBase
 {

  protected $step = 1;

1.2 Accesar el formulario padre

En lugar llamar a la función buildForm  de la clase padre al final, voy a realizar este llamado al inicio para modificar el form antes de sea enviado a renderizar.

/**
 * {@inheritdoc}
 */
public function buildForm(array $form, FormStateInterface $form_state) {
  $form = parent::buildForm($form, $form_state);

1.3 Filtrar elementos del form usando el Step

Ahora necesitamos filtrar qué elementos de formulario se renderizaran basado en valor del Step, como se puede ver en el siguiente fragmento de código.

if($this->step == 1) {
  $form['model'] = [
    '#type' => 'select',
    '#title' => $this->t('Model'),
    '#description' => $this->t(''),
          '#options' => array('1997', '1998', '1999', '2000', '2001', '2002', '2003', '2004', '2005', '2006', '2007', '2008', '2009', '2010', '2011', '2012', '2013', '2014', '2015'),
          '#default_value' => $config->get('model'),
  ];
}

1.4 Cambiar etiqueta del botón de submit

Ahora tenemos que modificar la etiqueta de botón submit para informar a los usuarios finales que hay un siguiente paso, o si llegamos a la final de múltiples pasos.

En nuestro caso sólo tenemos 3 pasos y el código seremos como este.

if($this->step < 3) {
  $button_label = $this->t('Next');
}
else {
  $button_label = $this->t('Find a Car');
}

$form['actions']['submit']['#value'] = $button_label;

return $form;

1.5 Habilitar Multi Step

Al final, necesitamos habilitar el comportamiento Multi Step en el Formulario, para hacer esto es necesario modificar el método submitForm forzando Formulario Rebuild si no llegamos todavía el último paso del Paso Multi utilizando el método setRebuild() parte de la Form State.

El método submitForm será similar al siguiente código

/**
 * {@inheritdoc}
 */
public function submitForm(array &$form, FormStateInterface $form_state) {
  if($this->step < 3) {
    $form_state->setRebuild();
    $this->step++;
  }
  else {
    parent::submitForm($form, $form_state);
    /*$this->config('multi_step.multi_step_form_config')
          ->set('model', $form_state->getValue('model'))
          ->set('body_style', $form_state->getValue('body_style'))
          ->set('gas_mileage', $form_state->getValue('gas_mileage'))
        ->save();*/
  }
}

Si quieres probar una implementación de Multi Step puedes descargar el el módulo drupal8_multi_step_form.

Espero que hayas encontrado esta entrada del blog útil