Drupal 8如何在Ajax回调后呈现表单?

时间:2019-05-18 16:29:00

标签: php ajax drupal drupal-8

我有一个包含多个步骤的表单,并且正在实施测验表单。 第一步是一个只有文本和提交按钮的欢迎屏幕,当用户按下开始(提交)按钮时,它将增加步骤并将其移至下一步,下一步具有不同的表单元素和提交按钮。

表单正常工作,我需要使用ajax更改表单,而无需重新加载整个页面。

以下代码演示了我当前没有ajax的表单类,并且按预期工作:

class QuestionsForm extends FormBase
{

    protected $definedSteps = 3;

    protected $questionService;

    protected $questions = [
        [
            'question_text' => 'Q1',
            'answers' =>
                [
                    '1' => 'a',
                    '2' => 'b'
                ]
        ],
        [
            'question_text' => 'Q2',
            'answers' =>
                [
                    '1' => 'a',
                    '2' => 'b'
                ]
        ],
        [
            'question_text' => 'Q3',
            'answers' =>
                [
                    '1' => 'a',
                    '2' => 'b'
                ]
        ],

    ];

    protected $step = '';
    protected $steps = [];
    protected $complete = FALSE;

    public function __construct()
    {


        $this->steps[0] = 0; // Create Hello Screen Step
        for ($i = 1; $i <= $this->definedSteps; $i++) {

            $this->steps[$i] = $i; // Create Questions Steps
            if ($i == $this->definedSteps) {
                $this->steps[$i + 1] = $i + 1; // Create Results Step
                $this->steps[$i + 2] = $i + 2; // Create Submit Data Step
            }
        }

        if (!$this->step) {
            $this->step = $this->steps[0];
        }

    }


    /**
     * {@inheritdoc}
     */
    public function getFormId()
    {
        return 'xxxform';
    }

    /**
     * {@inheritdoc}
     */
    public function buildForm(array $form, FormStateInterface $form_state)
    {


        if ($this->step == 0) {
            $this->stepStartScreen($form, $form_state);
        }
        else if ($this->step == 1) {
            $this->stepOne($form, $form_state);


        }
        else if ($this->step == 2) {
            $this->stepTwo($form, $form_state);
        }
        else if ($this->step == 3) {
            $this->stepThree($form, $form_state);
        }
        else if ($this->step == 4) {
            $this->stepResult($form, $form_state);
        }
        else if ($this->step == 5) {
            $this->stepReview($form, $form_state);
        }

        return $form;
    }

    /**
     * {@inheritdoc}
     */
    private function stepStartScreen(array &$form, FormStateInterface $form_state)
    {


        $form['welcome_message'] = [
            '#markup' => '<p id="welcome_text">Press start to begin!</p>',
        ];

        $form['actions']['next'] = [
            '#type' => 'submit',
            '#value' => $this->t('Next'),
            '#id' => 'next',
        ];

    }


    /**
     * {@inheritdoc}
     */
    private function stepOne(array &$form, FormStateInterface $form_state)
    {


        $form['q']['question'] = [
            '#type' => 'radios',
            '#title' => $this->questions[0]['question_text'],
            '#required' => TRUE,
            '#options' => $this->questions[0]['answers'],
        ];

        $form['actions']['next'] = [
            '#type' => 'submit',
            '#value' => $this->t('Next'),
            '#id' => 'next',
          '#ajax' => [
            'callback' => '::submitForm'
          ],

        ];

    }

    private function stepTwo(array &$form, FormStateInterface $form_state)
    {



        $form['q']['question'] = [
            '#type' => 'radios',
            '#title' => $this->questions[1]['question_text'],
            '#required' => TRUE,
            '#options' => $this->questions[1]['answers'],
        ];

        $form['actions']['next'] = [
            '#type' => 'submit',
            '#value' => $this->t('Next'),
            '#id' => 'next',

        ];



    }

    private function stepThree(array &$form, FormStateInterface $form_state)
    {


        $form['q']['question'] = [
            '#type' => 'radios',
            '#title' => $this->questions[2]['question_text'],
            '#required' => TRUE,
            '#options' => $this->questions[2]['answers'],
        ];

        $form['actions']['next'] = [
            '#type' => 'submit',
            '#value' => $this->t('Next'),
            '#id' => 'next',

        ];


    }
    /**
     * Review step of form
     *
     * @param array $form
     * @param \Drupal\Core\Form\FormStateInterface $form_state
     */
    private function stepResult(array &$form, FormStateInterface $form_state)
    {



        $form['actions']['try_again'] = [
            '#type' => 'submit',
            '#value' => $this->t('Try Again'),
            '#id' => 'try_again',
            '#validate' => [],
            '#limit_validation_errors' => [],
            '#submit' => [],
        ];

        $form['actions']['next'] = [
            '#type' => 'submit',
            '#value' => $this->t('Submit your score.'),
            '#id' => 'next',

        ];
    }


    /**
     * Review step of form
     *
     * @param array $form
     * @param \Drupal\Core\Form\FormStateInterface $form_state
     */
    private function stepReview(array &$form, FormStateInterface $form_state)
    {




        $form['review']['fullname'] = [
            '#type' => 'textfield',
            '#title' => $this->t('Full Name'),
            '#required' => TRUE,
        ];


        $form['review']['email'] = [
            '#type' => 'email',
            '#title' => $this->t('Email Address'),
            '#description' => $this->t('Enter your email address and you\'ll be entered into a prize draw'),
            '#default_value' => $email ? $email : NULL,
            '#required' => TRUE,
        ];


        $form['actions']['next'] = [
            '#type' => 'submit',
            '#value' => $this->t('Submit Result'),
            '#id' => 'next',
        ];
    }


    /**
     * @param array $form
     * @param \Drupal\Core\Form\FormStateInterface $form_state
     *
     * @throws \Exception
     */
    public function submitForm(array &$form, FormStateInterface $form_state)
    {

        $step_key = array_search($this->step, $this->steps);


        if ($this->step == $this->definedSteps + 2) {
            $this->stepReviewSubmit($form, $form_state);
        }

        if ($this->complete) {
            return;
        }


        if ($form_state->getTriggeringElement()['#id'] == 'back') {
            // Move to previous step
            $this->step = $this->steps[$step_key - 1];
        } else if ($form_state->getTriggeringElement()['#id'] == 'try_again') {


            return;
        } else {
            // Move to next step.
            $this->step = $this->steps[$step_key + 1];
        }

        $form_state->setRebuild();
    }


    /**
     * @param array $form
     * @param \Drupal\Core\Form\FormStateInterface $form_state
     *
     * @throws \Exception
     */
    public function stepReviewSubmit(array &$form, FormStateInterface &$form_state)
    {

        drupal_set_message($this->t('Thank you for your submission'), 'status');

        $this->complete = TRUE;
    }

}

我如何在提交后使用ajax替换旧的并添加新的表单来完成呈现表单的功能。

我只需要在步骤阶段使用ajax,所以一个表格可以是正常的,然后步骤表格应该使用ajax,在此之后的最后一个表格也可以是正常的。

很抱歉,长文本:)

我尝试执行的操作是对所有提交按钮使用一个像'#ajax'=> ['callback'=>':: submitForm']的ajax,然后在buildForm中返回响应而不是表单这些步骤具有相同功能,但不起作用:

 else if ($this->step == 2) {
            $this->stepTwo($form, $form_state);


            $renderer = \Drupal::service('renderer');
            $response = new AjaxResponse();
            $response->addCommand(new ReplaceCommand('#some_element',$renderer->render($x)));


            return $response;
        }

0 个答案:

没有答案