web-dev-qa-db-fra.com

Comment valider des éléments de formulaire dans un modal sans fermer?

J'utilise Drupal 8 et j'ai défini un type d'entité personnalisé 'my_entity_type', avec des gestionnaires de formulaires définis dans l'annotation @ContentEntityType:

 * @ContentEntityType(
 ...
 *   handlers = {
 *     "form" = {
 *       "add" = "Drupal\my_module\Form\MyEntityForm",
 *       "edit" = "Drupal\my_module\Form\MyEntityForm",
 *       "delete" = "Drupal\my_module\Form\MyEntityDeleteForm",
 ...

où:

  • MyEntityForm étend ContentEntityForm
  • MyEntityDeleteForm étend ContentEntityConfirmFormBase

Ceux-ci sont routés dans my_module.routing.yml en tirant parti de l'élément _entity_form:

_entity_form: my_entity_type.add

Je rend le formulaire d'un autre formulaire comme un modal:

$form['add_my_entity_button'] = [
  '#type' => 'link',
  '#title' => t('Add NewEntity'),
  '#url' => Url::fromRoute(
    'my_module.add_entity',
    array(
      'node' => is_numeric($node) ? $node : NULL,
    )
  ),
  '#attributes' => [
    'class' => ['button', 'use-ajax'],
    'data-dialog-type' => 'modal',
  ],
  '#attached' => [
    'library' => ['core/drupal.dialog.ajax'],
  ],
];

Tout fonctionne comme imaginé. Le validateur de type '#required' apparaît dans le formulaire dans le modal. Modal Validation Working

Objectif

Pour ajouter une validation personnalisée aux éléments de ce formulaire (validation 'live' qui ne ferme pas le modal). Je reconnais que ce type de problème n'est pas nouveau et je l'ai souvent fait sous des formes non modales. Les méthodes que j'utiliserais habituellement sont les suivantes:

  • Rappel de l'élément de formulaire '#element_validate'
  • type de rappel de formulaire validateForm ()

Les deux semblent exiger la soumission du formulaire, fermer le modal et afficher les erreurs dans un affichage de formulaire plat. J'ai ensuite fouillé dans Core pour trouver des idées et me suis lancé dans un voyage de rasage de yak remarquablement tordu:

  1. Ajout de validation via BaseFieldDefinition :: addConstraint dans l'entité baseFieldDefinitions () : Cela a toujours soumis le formulaire et a conduit à un formulaire plat (non modal) avec des erreurs correctement jeté. Une fois que j'ai résolu ce problème, je laisserai probablement cela pour servir de contrôleur d'accès au niveau du stockage.

  2. Étendre le 'nombre' FieldType via Plugin, étendre le widget, le type ou le stockage : Cela semblait trop complexe pour quelque chose d'aussi simple que d'ajouter un validateur. J'ai renoncé à cela avant d'aller trop loin, car j'ai considéré:

  3. Injection d'un rappel générique '#ajax' 'replace' à l'élément à l'intérieur de buildForm () dans MyEntityForm : Je n'ai PAS pu insérer ajax de cette manière pour déclencher ici.

  4. Injection d'un rappel générique '#ajax' 'replace' à l'élément dans hook_form_alter : Je ne pouvais PAS obtenir de rappels ajax insérés de cette manière pour déclencher non plus.

Des questions

Qu'est-ce que j'ai raté? Je pense que c'est simple. Y a-t-il quelque chose que j'ai manqué dans le formulaire qui définit la validation ajax simple?

Existe-t-il un moyen standard de valider les éléments de formulaire dans les modaux sans fermer le modal?

AJAX 'remplacer' les rappels peuvent être attachés à des formulaires définis et routés via l'annotation @ContentEntityType? Y a-t-il une restriction ici dans le pipeline de rendu?

5
Jake The Dweeb

Ceci est un excellent article que vous pouvez lire pour "résoudre" votre problème: http://www.mediacurrent.com/blog/loading-and-rendering-modal-forms-drupal-8

Gardez à l'esprit ces lignes:

Tout d'abord, nous enveloppons notre formulaire avec un div

public function buildForm(array $form, FormStateInterface $form_state, $options = NULL) {
  // It is important this id
  $form['#prefix'] = '<div id="modal_example_form">';
  $form['#suffix'] = '</div>';

  // The status messages that will contain any form errors.
  $form['status_messages'] = [
    '#type' => 'status_messages',
    '#weight' => -10,
  ];

  // more code

  $form['actions']['send'] = [
      '#type' => 'submit',
      '#value' => $this->t('Submit modal form'),
      '#attributes' => [
        'class' => [
          'use-ajax',
        ],
      ],
      // Function to call when the users click on submit button.
      '#ajax' => [
        'callback' => [$this, 'submitModalFormAjax'],
        'event' => 'click',
      ],
    ];

    // more code
}

Deuxièmement, nous montrons les erreurs:

/**
 * AJAX callback handler that displays any errors or a success message.
 */
public function submitModalFormAjax(array $form, FormStateInterface $form_state) {
  $response = new AjaxResponse();

  // If there are any form errors, re-display the form.
  if ($form_state->hasAnyErrors()) {
    // Remember the previous id ? Here it is
    $response->addCommand(new ReplaceCommand('#modal_example_form', $form));
  }
  else {
    $response->addCommand(new OpenModalDialogCommand("Success!", 'The modal form has been submitted.', ['width' => 800]));
  }

  return $response;
}
1
rpayanm