Agregar un controlador de envío personalizado a un formulario

19

¿Cómo puedo agregar un controlador de envío de formulario personalizado?

Traté de agregar $form['#submit'][] = 'mymodule_form_submit';o $form['actions']['submit']['#submit'][] = 'mymodule_form_submit';para hook_form_alter().

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

function MYMODULE_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  if ($form_id == 'node_trends_form' || $form_id == 'node_trends_edit_form') {
    foreach (array_keys($form['actions']) as $action) {
      if ($action != 'preview' && isset($form['actions'][$action]['#type']) && $form['actions'][$action]['#type'] === 'submit') {
        $form['actions']['submit']['#submit'][] = 'mymodule_form_submit';
      }
    }
  }
}
function mymodule_form_submit(array $form, FormStateInterface $form_state){
    //die("why won't this execute? :(");
    drupal_set_message("Why won't this message show?");
}

Parece drupal_set_message()que no se llama. También intenté reconstruir el caché, pero la función aún no se llama.

Estoy usando Drupal 8.2.3.

Yusef
fuente
Debería mostrar la implementación completa de hook_form_alter(), o es un poco más difícil decirle qué está haciendo mal. Además, debe decir qué forma está tratando de alterar.
kiamlaluno
@kiamlaluno agrego mi hook_form_alter.
Yusef
¿cuál es su código todavía $ form ['actions'] ['submit'] ['# submit']? Intenta reemplazar ['submit'] con [$ action].
MrD

Respuestas:

25

Si lo usa, hook_form_node_form_alter()puede usar el código de ejemplo :

function mymodule_form_node_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  foreach (array_keys($form['actions']) as $action) {
    if ($action != 'preview' && isset($form['actions'][$action]['#type']) && $form['actions'][$action]['#type'] === 'submit') {
      $form['actions'][$action]['#submit'][] = 'mymodule_form_submit';
    }
  }
}

y enviar función

function mymodule_form_submit(array $form, FormStateInterface $form_state){
    //die("I'm not getting run, why :(");
    drupal_set_message("Why won't this message show?");

}
MrD
fuente
1
$form['actions'][$action]['#submit'][]¿Qué documentación estás viendo? o hiciste un error tipográfico? En este documento hook_form_alter dice $form['actions']['submit']['#submit'][].
No Sssweat
1
Interesante, sí, tal vez necesite recorrer las acciones. Aunque, en esta otra P ¿Cómo implementa un controlador de envío personalizado en hook_form_alter ()? se supone que funciona de la manera en que lo está haciendo.
No Sssweat
3
Cada forma tiene diferentes estructuras. Entonces no hay una respuesta específica.
MrD
55
Consulte drupal.org/node/1901216 y drupal.org/node/2068063 para obtener más contexto sobre por qué es necesario ese ciclo
Berdir
18

Crear un complemento de controlador de formularios web personalizado para drupal 8.

Este documento asume que ya ha instalado y habilitado webform y webform-ui

1) Crea tu formulario web. - Vaya a estructura -> formularios web y presione el botón "+ Agregar formulario web". - Puedes usar la interfaz de usuario o usar yaml, eso depende de ti. ejemplo yaml para un formulario de un campo que toma una dirección de correo electrónico:

email:
  '#type': email
  '#title': email
  '#title_display': invisible
  '#placeholder': 'ENTER YOUR EMAIL'
  '#attributes':
    class:
      - my-ip

La sangría es importante para yaml, así que asegúrese de hacerlo bien. Las sangrías son espacios.

Ahora guarda tu formulario.

2) Crear un complemento de controlador de formulario web

A continuación, podemos crear un nuevo complemento que aparecerá en la sección "Correos electrónicos / controladores" al editar el formulario web. Lo llamaré myhandler, puedes llamarlo como quieras, siempre que reemplaces todas las menciones de myhandler con el nombre que elijas.

a) Cree una nueva carpeta para su complemento, haga esto en su raíz de drupal (a la que se hace referencia aquí / var / www / html /) en la siguiente subcarpeta: / var / www / html / modules / Custom / myhandler

b) Crear un nuevo archivo en el directorio anterior llamado myhandler.info.yml en este archivo va lo siguiente:

name: My Form Handler
description: handles form submits, does something with them. 
package: Custom
type: module
version: 1.0
core: 8.x

3) Cree un directorio src en el directorio de su módulo, por ejemplo: / var / www / html / modules / Custom / myhandler / src en src create Plugin en Plugin create WebformHandler

(esto se puede lograr de una vez usando

mkdir -p /var/www/html/modules/Custom/myhandler/src/Plugin/WebformHandler/ 

que hará que toda la estructura se ejecute de una vez usando la bandera -p para mkdir).

4) Crear un nuevo archivo /var/www/html/modules/Custom/myhandler/src/Plugin/WebformHandler/MyFormHandler.php

en ese archivo va el siguiente código php, dejé la configuración del formulario de configuración para que pueda ver cómo configurar su complemento si es necesario.

<?php
namespace Drupal\myhandler\Plugin\WebformHandler;

use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Serialization\Yaml;
use Drupal\Core\Form\FormStateInterface;
use Drupal\webform\Plugin\WebformHandlerBase;
use Drupal\webform\webformSubmissionInterface;


/**
 * Form submission handler.
 *
 * @WebformHandler(
 *   id = "myhandler_form_handler",
 *   label = @Translation("MyHandler form handler"),
 *   category = @Translation("Form Handler"),
 *   description = @Translation("Do something extra with form submissions"),
 *   cardinality = \Drupal\webform\Plugin\WebformHandlerInterface::CARDINALITY_SINGLE,
 *   results = \Drupal\webform\Plugin\WebformHandlerInterface::RESULTS_PROCESSED,
 * )
 */
class MyFormHandler extends WebformHandlerBase {

     /**
       * {@inheritdoc}
       */

     public function defaultConfiguration() {
        return [
            'submission_url' => 'https://api.example.org/SOME/ENDPOINT',
        ];
    }

    /**
     * {@inheritdoc}
     */
    public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
        $form['submission_url'] = [
            '#type' => 'textfield',
            '#title' => $this->t('Submission URL to api.example.org'),
            '#description' => $this->t('The URL to post the submission data to.'),
            '#default_value' => $this->configuration['submission_url'],
            '#required' => TRUE,
        ];
        return $form;
    }



  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state, WebformSubmissionInterface $webform_submission) {
    // Your code here.
        // Get an array of the values from the submission.

        $values = $webform_submission->getData();

        // Get the URL to post the data to.
        $post_url = $this->configuration['submission_url'];

        $message = "MyHandler got form data:".print_r($values,1); 
        \Drupal::logger('myformhandler')->error($message);

        return true;
 }
}   
?>

5) Habilite su módulo MyHandler (usando el menú drush o extend) y luego reconstruya su caché drupal ("drush cr" desde cualquier lugar debajo de su raíz drupal (/ var / www / html aquí) haría eso si usa drush)

6) edite su formulario web, vaya a "Correo electrónico / controladores" y haga clic en el botón "+ Agregar controlador" Debería ver su complemento en la lista, haga clic en Agregar controlador, ahora debería ver un cuadro que solicita la URL de envío. haga clic en el botón Guardar. Si algo no parece correcto o no funciona, revise el registro de errores de apache, es posible que encuentre algo útil allí.

7) Pruebe su formulario: realice un envío al formulario y luego verifique el registro de vigilancia (drush ws), debería ver los valores que se le envían. Pueden verse truncados en la salida que ves, no entres en pánico, todo está ahí. Lo que hagas con esto ahora depende de ti.

Espero que esto ayude a alguien. Lo combiné con cosas que encontré en el lugar y lo escribí en un solo documento. Gracias a los otros que me trajeron aquí.

CptnObvious
fuente
1
Si lo hago bien, lo único que falta en el código anterior para que el controlador funcione correctamente es el método submitConfigurationForm (), que consiste en parent::submitConfigurationForm($form, $form_state);y parent::applyFormStateToConfiguration($form_state);.
Hendrik
1
@Hendrik No, no lo necesitas. He creado un nuevo controlador con solo una submitForm()función y funciona. Todas las demás funciones están situadas en la clase base y no tengo necesidad de anularlas. Por cierto: una solución bastante agradable y simple una vez que lo
descubres
5

si usa hook_form_BASE_FORM_ID_alter en Drupal 8 core 8.4.3, descubrí que las formas de agregar el controlador de envío personalizado no funcionaron. Esto funcionó para agregar el nombre de la función del controlador de envío:

$form['#submit'][] = 'mymodule_submit_handler';

En otra situación, usando hook_form_FORM_ID_alter en Drupal 8.4.5, descubrí que lo anterior no funcionaba para agregar el controlador de envío personalizado. En cambio, esto funcionó:

$form['actions']['submit']['#submit'][]  = 'mymodule_submit_handler';
Anthony Fournier
fuente
1

La respuesta aceptada no funcionó para mí usando Drupal 8.7.7, tratando de agregar un controlador de envío a un formulario desde el search_apimódulo.

Recibí este error:

TypeError: Argument 2 passed to _my_module_search_api_form_submit() must be an instance of FormStateInterface, instance of Drupal\Core\Form\FormState given in ...

Para que funcione, cambié la firma de mi función al espacio de nombres completo de la interfaz:

function _my_module_search_api_form_submit(array $form, Drupal\Core\Form\FormStateInterface $form_state) { ...
usuario1359
fuente