Modifier un formulaire existant

12

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 de mise en œuvre 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é.

Jens Steppe
la source
2
Drupal 8 prend toujours en charge hook_form_alter(). Si vous avez juste besoin de rediriger le formulaire, il suffit d'ajouter un gestionnaire de soumission de formulaire qui effectue la redirection.
kiamlaluno
@kiamlaluno Cela devrait être la réponse je pense :)
Berdir
@Berdir Cela seul ne serait pas très utile, je le crains: ma connaissance de Drupal 8 est assez limitée. De plus, l'OP doit préciser ce que « modifier la save()méthode » en fait des moyens. Cela signifie-t-il changer la façon dont les données sont enregistrées, ou simplement faire une redirection? Dans le premier cas, la réponse est plus complexe.
kiamlaluno
@kiamlaluno Thx pour la réponse. Dans ce cas, il suffit de faire une redirection après la sauvegarde () pour que votre réponse fonctionne. Mais j'étais également intéressé par la façon de modifier d'autres choses dans la forme de la bonne façon Drupal 8. Par exemple le changement comment il est enregistré, ou ajouter des champs à la forme .. etc ..
Jens Steppe

Réponses:

4

J'ai dû faire exactement la même chose hier, et je suis toujours à la recherche d'un moyen plus Drupal 8 pour le faire, mais je ne l'ai pas trouvé. 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 :).

Dagomar
la source
3

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

Bien que cela fonctionne pour le user_login_form, cela ne fonctionnerait pas pour user_form. Car user_formje devais utiliser

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

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

Eric C.
la source
1

Eh bien, je voulais modifier le site_information_settingsformulaire 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 de la POO, alors j'ai commencé à écrire un service d'abonné de route en modifiant l' attribut de la system.site_information_settingsroute _form.

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 ... Maintenant, que se passe-t-il si un autre module réécrit également l'itinéraire 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_altersemble être le meilleur moyen de modifier un formulaire existant.

MacSim
la source
0

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_alteravec un gestionnaire de soumission 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.

googletorp
la source
0

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.

Kevin
la source
0

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 ceci

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

ruloweb
la source
0

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 a maintenant été entièrement construit, pas le cas dans le 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.

Rob C
la source
0

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');
}
Ioana Todea
la source