Modificar una forma existente

12

Recién comenzamos con Drupal 8 y muy rápidamente nos encontramos con nuestro primer problema.

¿Cómo debo alterar un formulario existente en Drupal 8?

Necesitamos alterar el método de guardar el formulario de nodo para hacer una redirección a otra página. Queremos modificar la forma del nodo para que se convierta en algo así como una forma de varios pasos. Después de que el usuario crea nuevo contenido, es redirigido a un nuevo formulario (que creamos) para obtener más información.

Resolvimos nuestro problema de implementación hook_entity_type_alter().

function mymodule_entity_type_alter(&$entity_info) {
  $handlers = $entity_info['node']->get('handlers');
  $handlers['form']['default'] =    'Drupal\mymodule\Form\MyExtendedNodeForm';
  $handlers['form']['edit'] = 'Drupal\mymodule\Form\MyExtendedNodeForm';
  $entity_info['node']->set('handlers', $handlers);
}

Luego creamos una nueva clase de formulario que extiende el formulario de nodo y altera el método de guardar.

class MyExtendedNodeForm extends NodeForm {

    public function save(array $form, FormStateInterface $form_state) {
      parent::save($form, $form_state);
      $node = $this->entity;
      $form_state->setRedirect('entity.regions.add_form', ['nid' => $node->id()]);
  }

}

Esto funciona perfectamente, pero ¿es bueno? Si otro módulo hace lo mismo, nuestro código ya no se ejecuta.

Jens Estepa
fuente
2
Drupal 8 todavía es compatible hook_form_alter(). Si solo necesita redirigir el formulario, es suficiente agregar un controlador de envío de formulario que redirija.
kiamlaluno
@kiamlaluno Esa debería ser la respuesta, creo :)
Berdir
@ Berdir Eso por sí solo no sería de mucha ayuda, me temo: mi conocimiento de Drupal 8 es bastante limitado. Además, el OP debe dejar en claro qué significa "alterar el save()método". ¿Significa cambiar la forma en que se guardan los datos, o simplemente hacer una redirección? En el primer caso, la respuesta es más compleja.
kiamlaluno
@kiamlaluno Thx por la respuesta. En este caso, solo necesitamos hacer una redirección después del save () para que su respuesta funcione. Pero también estaba interesado en cómo alterar otras cosas en la forma de la manera correcta de Drupal 8. Por ejemplo, cambie cómo se guarda o agregue campos al formulario ... etc.
Jens Steppe

Respuestas:

4

Tuve que hacer exactamente lo mismo ayer, y todavía estoy buscando una forma más de Drupal 8 para hacer esto, pero no la he encontrado. Terminé haciéndolo de esta manera:

<?php

/**
 * @file
 * This is my module.
 */

use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\HttpFoundation\Request;

/**
 * Implements hook_form_alter().
 */
function MODULE_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
  if ($form_id == 'user_form') {
    $form['actions']['submit']['#submit'][] = '_MODULE_goto';
  }
}

/**
 * Make the form go to route.id.
 */
function _MODULE_goto($form, FormStateInterface $form_state) {
  $form_state->setRedirect('route.id');
}

Todavía estoy muy interesado en hacerlo de una manera diferente, mi módulo se veía tan limpio sin el archivo .module :).

Dagomar
fuente
3

Estoy usando Drupal 8.1.1 y estaba tratando de redirigir a los usuarios después de que modificaron su cuenta, es decir, haciendo clic en el botón Guardar en la página / usuario / editar. Inicialmente intenté esto:

/**
 * Implements hook_form_alter().
*/
function MODULE_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
  if ($form_id == 'user_form') {
    $form['#submit'][] = '_MODULE_goto';
  }
}

Si bien eso funcionó para el user_login_form, no funcionaría user_form. Porque user_formtuve que usar

$form['actions']['submit']['#submit'][] = '_MODULE_goto';

¡Espero que eso ayude a otros que se encuentran con el mismo problema!

Eric C.
fuente
1

Bueno, quería alterar el site_information_settingsformulario para agregar algunos campos.

Como tú, tuve que elegir entre

  • hook_form_alter(o hook_form_FORM_ID_alter)
  • extender la clase de formulario original

Quería hacer algo de OOP, así que comencé a escribir un servicio de suscriptor de ruta alterando el atributo de la system.site_information_settingsruta _form.

Luego, en mi nueva clase extendiendo SiteInformationForm, después de que se hayan agregado los campos y sus validadores y la función de envío extendida, sentí exactamente lo mismo que usted ... Ahora, ¿qué pasa si otro módulo reescribe la ruta del formulario y usa su propia clase?

De vuelta al principio, tenía que elegir entre dos opciones ... parece que elegí la incorrecta.

hook_form_alter/ hook_form_FORM_ID_alterParece ser la mejor manera de alterar un formulario existente.

MacSim
fuente
0

Parece lo que quiere hacer, no es realmente alterar el método de guardar, sino cambiar la redirección cuando se guarda un nodo.

En esta situación, hacer mucho como Drupal 7, hook_form_alterjunto con un controlador de envío personalizado (en el formulario o en el botón, dependiendo del formulario y los requisitos) sería una buena solución.

Lo que describe en la pregunta también funciona, pero evitaría sobrescribir la clase base, a menos que realmente quiera cambiar algo en la clase.

El método de guardar solo se usa como un controlador de envío de todos modos, por lo que no tiene mucho sentido sobrescribir solo para agregar una redirección.

googletorp
fuente
0

Creo que el mejor método es seguir utilizando uno de los ganchos de la familia form_alter, adjunto un controlador de envío y dentro de eso establecer su redirección.

Contrib extender las clases base para hacer esto es difícil en mi opinión. Especialmente porque ninguna función está cambiando, solo redirige.

Kevin
fuente
0

Puede crear un nuevo EventSubscriber que escuche el evento KernelEvents :: REQUEST, y luego reaccionar cuando envíe un formulario de nodo, algo como esto

De todos modos, la forma hook_form_alter funciona bien.

ruloweb
fuente
0

Lo que he encontrado hasta ahora: Implementar un formulario alter hook e intentar cambiar los manejadores de validación / envío en el formulario alter hook solo funciona si cambia los manejadores $ form ['# validate] / $ form [#submit']. (llamar a las funciones form_state para esto no funcionará en el formulario alter hook)

Pero cuando prueba esto dentro de un controlador de validación, tiende a funcionar:

// Load form submit handlers.
$submit_handlers = $form_state->getSubmitHandlers();

// Drop the core entity submitForm function.
$key_core_submit = array_search('::submitForm', $submit_handlers);
if ($key_core_submit !== FALSE) {
  unset($submit_handlers[$key_core_submit]);
  // Add your own submit handler.
  array_unshift($submit_handlers, 'yourmodule_submit_handler');
}
// Update submit handlers.
$form_state->setSubmitHandlers($submit_handlers);

Esto se debe a que el formulario ahora se ha creado completamente, no el caso en el formulario después del enlace.

La idea es: puede agregar un controlador de validación como el último, evaluar otros controladores que existen para el envío y cambiarlos allí mismo.

Si también desea cambiar los controladores de validación, asegúrese de que el suyo se ejecute antes que cualquier otro y cambie lo que desea en el controlador de validación.

Todavía estoy buscando una mejor manera, siempre necesito reemplazar los controladores de validación / envío para el formulario de registro de usuario. Pero podrían existir otros módulos que rompan la implementación de mis módulos. Por lo tanto, mi módulo necesitaría poder verificar esto, y eso es posible de esta manera. Me pregunto si existe alguna forma de entidad después de la función de compilación para lograr esto. (algo que se ejecuta cuando el formulario se ha completado y está a punto de entregarse) (esa no es una forma compleja para este caso simple)

Omitir la redirección del método save () no es posible, pero deshabilitar save () es de esta manera (+ implementa el tuyo). Es cierto que una clase es más agradable y ofrece un acceso más fácil a objetos / etc., pero anular una clase central de hecho conduce a problemas cuando otros módulos quieren usarlos. Ese no es el caso si usa este código.

Rob C
fuente
0

Después de verificar este problema, esto es lo que he encontrado que debería adaptarse a su caso:

/**
 * Implements hook_entity_type_alter().
 */
function mymodule_entity_type_alter(&$entity_info) {
 $entity_info['node']->setFormClass('edit','Drupal\mymodule\Form\CustomNodeForm');
}
Ioana Todea
fuente