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.
hook_form_alter()
. Si solo necesita redirigir el formulario, es suficiente agregar un controlador de envío de formulario que redirija.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.Respuestas:
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:
Todavía estoy muy interesado en hacerlo de una manera diferente, mi módulo se veía tan limpio sin el archivo .module :).
fuente
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:
Si bien eso funcionó para el
user_login_form
, no funcionaríauser_form
. Porqueuser_form
tuve que usar¡Espero que eso ayude a otros que se encuentran con el mismo problema!
fuente
Bueno, quería alterar el
site_information_settings
formulario para agregar algunos campos.Como tú, tuve que elegir entre
hook_form_alter
(ohook_form_FORM_ID_alter
)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_settings
ruta_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_alter
Parece ser la mejor manera de alterar un formulario existente.fuente
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_alter
junto 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.
fuente
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.
fuente
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.
fuente
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:
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.
fuente
Después de verificar este problema, esto es lo que he encontrado que debería adaptarse a su caso:
fuente