2016-01-06 1 views
3

J'ai un problème avec plusieurs requêtes AJAX modification d'un formulaire dans drupal 8.Drupal 8 Ajax forme oublier les changements

Permettez-moi d'expliquer - je suis en train de construire un module de jeu-questionnaire au sein de Drupal, et a décidé d'utiliser un widget pour créer une quantité variable de questions de quiz, au sein de cette question widget est une liste de réponses possibles. J'ai créé un bouton AJAX dans mon widget de question qui permet de retirer les réponses et cela fonctionne la première fois qu'il est soumis, mais pour une raison quelconque la deuxième fois que j'exécute l'appel ajax le formulaire est réinitialisé (comme aucun changement n'a été fait et aucune réponse n'a été supprimée). J'ai débogué le tableau de forme après que j'ai une réponse non définie, ainsi que lorsque le rappel ajax est exécuté la deuxième fois. Le bouton ajax-enabled utilise la méthode ajax replace par défaut et j'ai essayé différentes méthodes pour retourner le formulaire (moins une réponse) dans mon callback AJAX, y compris simplement en désactivant l'élément de formulaire sélectionné et en retournant le formulaire, ainsi que l'utilisation du AjaxResponse et HtmlCommand classes. J'ai également essayé de reconstruire à la fois le formulaire, via formbuilder, et form_state sans joie. De plus, chaque bouton et chaque réponse ont des noms/identifiants uniques.

Voici mon code widget (y compris la définition du bouton):

<?php 
/** 
* @file 
* Contains \Drupal\pp_quiz\Plugin\Field\FieldWidget\QuestionWidget. 
*/ 
namespace Drupal\pp_quiz\Plugin\Field\FieldWidget; 

use Drupal\pp_quiz\Controller\QuizController; 
use Drupal\pp_quiz\Ajax\AjaxHandler; 
use Drupal\Core\Field\WidgetBase; 
use Drupal\Core\Field\FieldItemListInterface; 
use Drupal\Core\Form\FormStateInterface; 

/** 
* Plugin implementation of the 'question_widget' widget 
* 
* @FieldWidget(
* id = "question_widget", 
* label = @Translation("Quiz question widget"), 
* field_types = { 
*  "quizquestion_type", 
* }, 
*) 
*/ 
class QuestionWidget extends WidgetBase 
{ 
    public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) { 
     $ajaxhandler = new AjaxHandler(); 

     $input = $form_state->getUserInput(); 

     //grab answer count from element array (using delta index) 
     $question = $items->get($delta)->getValue(); 
     $answercount = count(unserialize($question['answer'])); 

     $element['question'] = array(
      '#type'=>'text_format', 
      '#format' => 'normal', 
      '#title' => gettext('Question'), 
      '#description' => gettext("The Question Text"), 
      '#required' => TRUE, 
      '#element_validate' => array(
       array(
        '\Drupal\pp_quiz\Controller\QuizController', 
        'validateQuestion' 
       ), 
      ), 
     ); 
     $element['answers_description'] = array('#markup' => 'Create answers below and select which are correct by checking boxes'); 
     $tableheader = array(
      'answer' => array('data' => t('Answer'), 'field' => 'answer'), 
     ); 

     for ($i=0; $i<$answercount; $i++) { 
      $name = "{$delta}answer{$i}"; 

      $options[$name] = array(
       'answer' => array(
        'data' => array(
         '#type'=>'textfield', 
         //fix for losing answers on addmore button 
         '#value'=>isset($input[$name]) ? $input[$name] : '', 
         '#name' => $name, 
         '#required' => TRUE, 
        ), 
       ), 
      ); 
     } 

     $element['answers'] = array(
      '#type'=>'tableselect', 
      '#header' => $tableheader, 
      '#options' => $options, 
     ); 

     $element['removeanswer'] = array(
      '#type' => 'submit', 
      '#value' => t('Remove Answer'), 
      '#name' => "{$delta}removeanswer", 
      '#questionno' => $delta, 
      '#attributes' => array(
       'class' => array('removeanswer') 
      ), 
      '#ajax' => array(
       'callback' => array(
        $ajaxhandler, 
        'removeAnswerAjax', 
       ), 
       'wrapper' => 'edit-field-quiz-questions-wrapper', 
      ), 

     ); 

     $element = array(
      '#type' => 'question', 
     ) + $element; 

     return $element; 
    } 
} 

Comme vous pouvez le voir ci-dessus, mon « removeanswer » soumettre élément de bouton a une fonction de rappel ajax à une fonction appelée « removeAnswerAjax » sur la classe 'AjaxHandler'. Voici le code pour ce rappel:

<?php 

/** 
* @file 
* Contains \Drupal\pp_quiz\Ajax\AjaxHandler. 
*/ 

namespace Drupal\pp_quiz\Ajax; 

use \Drupal\pp_quiz\Controller\QuizController; 
use \Drupal\pp_quiz\Entities\QuizResults; 
use \Drupal\Core\Form\FormStateInterface; 
use \Drupal\Core\Ajax\AjaxResponse; 
use \Drupal\Core\Ajax\HtmlCommand; 

class AjaxHandler { 

    public function removeAnswerAjax(&$form, FormStateInterface $form_state) { 
     $questionno = $form_state->getTriggeringElement()['#questionno']; 

     $response = new AjaxResponse(); 

     //find selected answer for question number (questionno) 
     foreach($form['field_quiz_questions']['widget'][$questionno]['answers']['#value'] as $answer_key=>$answer) { 
      unset($form['field_quiz_questions']['widget'][$questionno]['answers']['#options'][$answer]); 
      unset($form['field_quiz_questions']['widget'][$questionno]['answers']['#default_value'][$answer]); 
      unset($form['field_quiz_questions']['widget'][$questionno]['answers'][$answer]); 
     } 

     $response->addCommand(new HtmlCommand('#edit-field-quiz-questions-wrapper', $form['field_quiz_questions']['widget'])); 

     $form_state->setRebuild(); 

     return $response; 
    } 
} 

Si quelqu'un pouvait faire la lumière sur la raison pour laquelle le formulaire est remis à zéro avant qu'il ne soit passé comme argument à mon rappel ajax, je vous aimerai toujours :-)

Merci d'avoir lu.

+0

L'avez-vous découvert? –

Répondre

1

Une raison possible que votre Ajax ne prend pas effet la deuxième fois est la reconstruction du formulaire, dans le rappel Ajax. Comme vous reconstruisez le formulaire en utilisant -

$form_state->setRebuild() 

Lorsqu'un formulaire est reconstruit, tout le champ et la forme sont ids suffixé par un numéro de version aléatoire. ainsi le sélecteur n'est pas trouvé et la réponse n'est pas remplacée dans DOM.

Essayez de supprimer la reconstruction de formulaire.

+0

Grâce à vous, j'ai réussi à trouver comment faire Ajax soumettre formulaire de reconstruction sans valeurs. Pouvez-vous me montrer du doigt tout processus de construction/reconstruction? Je veux dire où ça commence-finit. Je découvre le reste. – red777