web-dev-qa-db-fra.com

Ajout dynamique de champs au formulaire

Hy,

J'essaie de créer un formulaire dans lequel vous pouvez remplir des noms d'utilisateur. Je veux ajouter dynamiquement de nouveaux champs de texte en appuyant sur un bouton. J'ai basé mon code sur le question suivante (car il utilise également drupal 8 et devrait fonctionner)).

Cependant, malheureusement, il n'ajoute pas les champs. Le code que j'utilise actuellement ressemble à ceci:

<?php
    /**
     * @file
     * Contains \Drupal\bulk_email\Form\EmailForm.
     */

    namespace Drupal\bulk_email\Form;
    use Drupal\Core\Form\FormBase;
    use Drupal\Core\Form\FormStateInterface;
    use Drupal\Component\Utility\UrlHelper;

    class EmailForm extends FormBase {
        public function getFormId() {
            return "bulk_email_form";
        }

        public function buildForm(array $form, FormStateInterface $form_state) {
            $form['#tree'] = TRUE;

            $form['users'] = array(
              '#type' => 'fieldset',
              '#title' => t('Users'),
              '#prefix' => '<div id="users-wrapper">',
              '#suffix' => '</div>',
            );

            $num_users = $form_state->getValue('num_users');
            if (empty($num_users)) {
                $num_users = 1;
            }
            for ($i = 0; $i < $num_users; $i++) {
                $form['users'][$i] = array(
                    '#type'  => 'textfield',
                    '#description' => t('Select a user.'),
                );
            }

            $form['users']['users_more'] = array(
                '#type' => 'submit',
                '#value' => t('Add one'),
                '#submit' => array($this, 'bulk_email_addfieldsubmit'),
                '#ajax' => array(
                     'callback' => array($this, 'bulk_email_add_more_callback'),
                     'wrapper' => 'users-wrapper',
                ),
            );

            $form['actions'] = array('#type' => 'actions');
            $form['submit'] = array(
                '#type' => 'submit',
                '#value' => t('Send'),
            );
            return $form;
        }

        public function submitForm(array &$form, FormStateInterface $form_state) {
            // submit code
        }

        public function bulk_email_addfieldsubmit(array &$form, FormStateInterface $form_state) {
            $num_users = $form_state->get('num_users') + 1;
            $form_state->set('num_users', $num_users);
            $form_state->setRebuild(TRUE);
        }

        public function bulk_email_add_more_callback(array &$form, FormStateInterface $form_state) {
            return $form['users'];
        }
    }
?>

Je manque probablement un petit détail, mais je n'arrive pas à le trouver ... Toute aide est appréciée.

Sincères amitiés.

2
Matthias Verstraete

Je peux me tromper, mais vous pouvez également essayer de changer le rappel ajax en supposant que bulk_email_add_more_callback n'est pas réellement appelé.

'#ajax' => array(
                 'callback' => '::bulk_email_add_more_callback',
                 'wrapper' => 'users-wrapper',
            ),

Et puis dans le rappel réel, obtenez vos valeurs à partir du formulaire complet. C'était mon problème, toutes les valeurs étaient correctes, mais j'ai renvoyé les anciennes valeurs.

public function bulk_email_add_more_callback(array &$form, FormStateInterface $form_state) {
        $form = $form_state->getCompleteForm()
        return $form['users'];
    }
1
Johann

Je n'ai trouvé aucune solution à mon problème et j'ai commencé à me demander s'il s'agissait d'une mauvaise décision de conception ou d'un bug.

Quoi qu'il en soit, pour d'autres utilisateurs, j'ai utilisé la solution de contournement suivante:

Tout d'abord, j'ai supprimé tout le code lors de l'ajout de ces champs supplémentaires. Je n'ai gardé que le champ de texte réel où vous entrez le nom d'utilisateur. Ensuite, j'ai ajouté un nouveau champ caché appelé collection d'utilisateurs.

Le reste a été fait en ajoutant un javascript personnalisé. Ce script détecterait si un nom d'utilisateur a été entré (basé sur la saisie semi-automatique). Il ajouterait alors ";" à la valeur de la collection d'utilisateurs. Il efface ensuite le champ de texte. Le résultat est un champ de collecte d'utilisateurs, contenant tous les noms d'utilisateur entrés. J'ai enfin ajouté un retour visuel qui montrait le contenu de la collection d'utilisateurs (après quelques analyses).

Ce n'est qu'un travail et cela m'a aussi demandé beaucoup d'efforts, mais c'est mieux que rien.

1

Avez-vous vérifié si la soumission est appelée dans votre demande ajax?

public function bulk_email_addfieldsubmit(array &$form, FormStateInterface $form_state) {
    $num_users = $form_state->get('num_users') + 1;
    $form_state->set('num_users', $num_users);

Sinon, vous pouvez mettre ce code dans buildForm(). Dans ce cas, vous devez vérifier si l'élément déclencheur est le bon.

Et un autre petit problème, cette ligne dans buildForm():

$num_users = $form_state->getValue('num_users');

Doit être get('num_users'), car getValue() est destiné à l'utilisateur.

1
4k4

vous pouvez utiliser quelque chose comme ça.

if (!empty($form_state['values']['field_name'])) {
    $form[]=array();//add your form elements to be shown after submit.
}
else {
    $form[]=array();//here your original form.
}
return $form;

dans votre formulaire soumettre ajouter

$form_State['rebuild']=true;
1
ana

j'ai aussi le même scénario. je peux ajouter et supprimer les champs de texte de manière dynamique avec succès en utilisant ajax dans drupal 8. j'ai attaché le code ci-dessous.

il y a un problème dans fapi ajouter plus de forme dans drupal 8. et le patch est également là. donc mon auto a corrigé le code de mon scénario.

Première étape: nous travaillons derrière la logique des variables formstate. la valeur des variables formstate nous pouvons ajouter ou soustraire les champs dynamiquement.

vous devez définir la propriété $ form ['# tree'] = TRUE; lors de la création initiale du formulaire de fonction. Vous ne pouvez alors obtenir que les valeurs soumises appropriées dans la fonction de soumission.

 $veritas_id = $form_state->get('veritas_id');
if ($veritas_id === NULL) {
  $veritas_id = $form_state->set('veritas_id', 0);
  $veritas_id = 0;
  }

deuxième étape

$form['veritasIds'] = [
  '#type' => 'fieldset',
  //'#title' => $this->t('#ID'),
  '#prefix' => '<div id="veritas-id-wrapper">',
  '#suffix' => '</div>',
  ];



  $form['veritasIds']['actions']['add_name'] = [
  '#type' => 'submit',
  '#limit_validation_errors' => array(),
  '#value' => t('add row'),
  //'#name'=>$veritas,
  '#submit' => array('::addOneVeritas'),
  '#ajax' => [
  'callback' => '::addmoreCallbackVeritas',
  'wrapper' => 'veritas-id-wrapper',
  ],

  '#attributes' => array('class'=> array('btn-transparent')),
  ];

  //if ($num_names > 1) {

  $form['veritasIds']['actions']['remove_name'] = [
  '#type' => 'submit',
  '#limit_validation_errors' => array(),
  '#value' => t('delete row'),
  '#submit' => array('::removeoneVeritas'),
  '#ajax' => [
    'callback' => '::addmoreCallbackVeritas',
    'wrapper' => 'veritas-id-wrapper',
  ],
  '#name'=>t('veritasremove'),

  '#attributes' => array('class'=> array('btn-transparent')),
  '#suffix' => t('<div class="id-wrapper">#ID</div>'),
  ];

  for ($i = 0; $i < $veritas_id; $i++) {
  $form['veritasIds']['id'][$i] = [
  '#type' => 'textfield',
  '#attributes' => array('class'=> array('veritas-addfield')),
  //'#title' => t('Name'),
  ];
  }

ici, je crée un fieldset. à l'intérieur du jeu de champs, ajoutez seulement une ligne de plus et supprimez plus de bouton et les champs dynamiques ajoutés seront là.

troisième étape $ form_state-> setCached (FALSE); est nécessaire soumettre et les fonctions de rappel ajax seront

public function addmoreCallbackVeritas(array &$form, FormStateInterface $form_state) {
  $veritas_id = $form_state->get('veritas_id');
  return $form['veritasIds'];

}

public function addOneVeritas(array &$form, FormStateInterface $form_state) {
    $veritas_id = $form_state->get('veritas_id');
    $add_button1 = $veritas_id + 1;
    $form_state->set('veritas_id', $add_button1);
    $form_state->setRebuild();
  }

n'hésitez pas à poser des doutes dans ce

1
Vinodhini