我有一个包含多个步骤的表单,并且正在实施测验表单。 第一步是一个只有文本和提交按钮的欢迎屏幕,当用户按下开始(提交)按钮时,它将增加步骤并将其移至下一步,下一步具有不同的表单元素和提交按钮。
表单正常工作,我需要使用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;
}