web-dev-qa-db-fra.com

Modifier un formulaire existant

Nous venons de commencer avec Drupal 8 et très rapidement nous avons rencontré notre premier problème.

Comment modifier un formulaire existant dans Drupal 8?

Nous devons modifier la méthode d'enregistrement du formulaire de nœud pour effectuer une redirection vers une autre page. Nous voulons modifier la forme du nœud pour devenir quelque chose comme une forme à plusieurs étapes. Une fois que l'utilisateur a créé un nouveau contenu, il est redirigé vers un nouveau formulaire (que nous avons créé) pour obtenir plus d'informations.

Nous avons résolu notre problème d'implémentation de 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);
}

Nous avons ensuite créé une nouvelle classe de formulaire qui étend la forme du nœud et modifie la méthode de sauvegarde.

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()]);
  }

}

Cela fonctionne parfaitement, mais est-ce bien? Si un autre module fait de même, notre code n'est plus exécuté.

12
Jens Steppe

J'ai dû faire exactement la même chose hier, et je suis toujours à la recherche d'une manière plus Drupal 8 pour le faire, mais je ne l'ai pas trouvée. J'ai fini par le faire de cette façon:

<?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');
}

Je suis toujours très intéressé à le faire d'une manière différente, mon module avait l'air si propre sans le fichier .module :).

5
Dagomar

J'utilise Drupal 8.1.1 et essayais de rediriger les utilisateurs après avoir modifié leur compte, c'est-à-dire en cliquant sur le bouton Enregistrer sur la page/user/edit. J'ai d'abord essayé ceci:

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

Alors que cela a fonctionné pour le user_login_form, cela ne fonctionnerait pas pour user_form. Pour user_form Je devais utiliser

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

J'espère que cela aide ceux qui tombent sur le même problème!

4
Eric C.

Eh bien, je voulais modifier le site_information_settings formulaire pour ajouter des champs.

Comme vous, j'avais le choix entre

  • hook_form_alter (ou hook_form_FORM_ID_alter)
  • étendre la classe de formulaire d'origine

Je voulais faire un OOP alors j'ai commencé à écrire un service d'abonné de route en modifiant le system.site_information_settings la route _form attribut.

Ensuite, dans ma nouvelle classe étendant le SiteInformationForm, après que les champs et leurs validateurs ont été ajoutés et la fonction de soumission étendue, je me suis senti exactement de la même manière que vous ... Et maintenant, si un autre module réécrit le la route du formulaire pour utiliser sa propre classe?

Retour au début, j'avais le choix entre deux options ... semble avoir choisi la mauvaise.

hook_form_alter/hook_form_FORM_ID_alter semble être le meilleur moyen de modifier un formulaire existant.

2
MacSim

Vous pouvez créer un nouvel EventSubscriber qui écoute l'événement KernelEvents :: REQUEST, puis réagir lorsque vous soumettez un formulaire de nœud, quelque chose comme this

Quoi qu'il en soit, la méthode hook_form_alter fonctionne bien.

0
ruloweb

Cela ressemble à ce que vous voulez faire, ce n'est pas vraiment pour modifier la méthode de sauvegarde, mais pour changer la redirection lorsqu'un nœud est enregistré.

Dans cette situation, faire un peu comme Drupal 7, hook_form_alter avec un gestionnaire d'envoi personnalisé (sur le formulaire ou le bouton, selon le formulaire et les exigences) serait une bonne solution.

Ce que vous décrivez dans la question fonctionne également, mais j'éviterais d'écraser la classe de base, sauf si je veux réellement changer quelque chose dans la classe.

De toute façon, la méthode de sauvegarde n'est utilisée que comme gestionnaire de soumission, il n'est donc pas très logique d'écraser simplement pour ajouter une redirection.

0
googletorp

Je pense que la meilleure méthode consiste à utiliser toujours l'un des crochets de la famille form_alter, à joindre un gestionnaire de soumission et à l'intérieur de celui-ci, définissez votre redirection.

Contribuer à étendre les classes de base pour ce faire est velu à mon avis. D'autant plus qu'aucune fonction ne change, juste rediriger.

0
Kevin

Ce que j'ai trouvé jusqu'à présent: implémenter un formulaire alter hook et essayer de modifier les gestionnaires de validation/soumission dans le formulaire alter hook lui-même ne fonctionne que si vous modifiez les gestionnaires $ form ['# validate]/$ form [#submit']. (appeler les fonctions form_state pour cela ne fonctionnera pas sous la forme alter hook elle-même)

Mais lorsque vous essayez ceci dans un gestionnaire de validation, cela a tendance à fonctionner:

// 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);

Cela est dû au fait que le formulaire est désormais entièrement construit, et non au cas du formulaire alter hook lui-même.

L'idée est la suivante: vous pouvez ajouter un gestionnaire de validation comme dernier, évaluer d'autres gestionnaires qui existent pour la soumission et les modifier directement.

Si vous souhaitez également modifier les gestionnaires de validation, assurez-vous que le vôtre s'exécute avant tout autre et modifiez ce que vous voulez dans le gestionnaire de validation.

Toujours à la recherche d'un meilleur moyen moi-même, je dois toujours remplacer les gestionnaires de validation/soumission pour le formulaire d'inscription d'utilisateur. Mais d'autres modules pourraient exister qui cassent la mise en œuvre de mes modules. Donc, mon module devrait pouvoir vérifier ces derniers, et c'est possible de cette façon. Je me demande si une forme d'entité après la fonction de construction existe pour y parvenir. (quelque chose qui s'exécute lorsque le formulaire est rempli et est sur le point d'être livré) (ce n'est pas trop compliqué pour ce cas simple)

Il n'est pas possible de contourner la redirection de la méthode save (), mais la désactivation de save () se fait de cette façon (+ implémentez la vôtre). Certes, une classe est plus agréable et offre un accès plus facile aux objets/etc, mais remplacer une classe principale entraîne en effet des problèmes lorsque d'autres modules souhaitent les utiliser. Ce n'est pas le cas si vous utilisez ce code.

0
Rob C

Après avoir vérifié ce problème, voici ce que j'ai trouvé qui devrait convenir à votre cas:

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