Wizard.php 7.11 KB
Newer Older
1
2
3
4
5
6
7
8
<?php

namespace Drupal\ajax_example\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\Core\Link;
9
use Symfony\Component\DependencyInjection\ContainerInterface;
10
11
12
13
14
15
16
17
18
19
20
21
22

/**
 * AJAX example wizard.
 */
class Wizard extends FormBase {

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

23
24
25
26
27
28
29
30
31
32
33
34
  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    // Since FormBase uses service traits, we can inject these services without
    // adding our own __construct() method.
    $form = new static($container);
    $form->setStringTranslation($container->get('string_translation'));
    $form->setMessenger($container->get('messenger'));
    return $form;
  }

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state, $no_js_use = FALSE) {
    $url = Url::fromUri('internal:/examples/ajax-example/wizard-nojs');
    $link = Link::fromTextAndUrl($this->t('examples/ajax-example/wizard-nojs'), $url)
      ->toString();

    // Prepare link for multiple arguments.
    $urltwo = Url::fromUri('internal:/examples/ajax-example/wizard');
    $linktwo = Link::fromTextAndUrl($this->t('examples/ajax-example/wizard'), $urltwo)
      ->toString();

    // We want to deal with hierarchical form values.
    $form['#tree'] = TRUE;
    $form['description'] = [
51
      '#markup' => $this->t('This example is a step-by-step wizard. The @link does it without page reloads; the @link1 is the same code but simulates a non-javascript environment, showing it with page reloads.', [
52
53
54
55
56
57
        '@link' => $linktwo,
        '@link1' => $link,
      ]),
    ];

    $form['step'] = [
58
      '#type' => 'value',
59
60
61
      '#value' => !empty($form_state->getValue('step')) ? $form_state->getValue('step') : 1,
    ];

62
63
64
65
66
67
68
69
70
71
72
73
74
75
    switch ($form['step']['#value']) {
      case 1:
        $limit_validation_errors = [['step']];
        $form['step1'] = [
          '#type' => 'fieldset',
          '#title' => $this->t('Step 1: Personal details'),
        ];
        $form['step1']['name'] = [
          '#type' => 'textfield',
          '#title' => $this->t('Your name'),
          '#default_value' => $form_state->hasValue(['step1', 'name']) ? $form_state->getValue(['step1', 'name']) : '',
          '#required' => TRUE,
        ];
        break;
76

77
78
79
80
81
82
83
84
      case 2:
        $limit_validation_errors = [['step'], ['step1']];
        $form['step1'] = [
          '#type' => 'value',
          '#value' => $form_state->getValue('step1'),
        ];
        $form['step2'] = [
          '#type' => 'fieldset',
85
          '#title' => $this->t('Step 2: Street address info'),
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
        ];
        $form['step2']['address'] = [
          '#type' => 'textfield',
          '#title' => $this->t('Your street address'),
          '#default_value' => $form_state->hasValue(['step2', 'address']) ? $form_state->getValue(['step2', 'address']) : '',
          '#required' => TRUE,
        ];
        break;

      case 3:
        $limit_validation_errors = [['step'], ['step1'], ['step2']];
        $form['step1'] = [
          '#type' => 'value',
          '#value' => $form_state->getValue('step1'),
        ];
        $form['step2'] = [
          '#type' => 'value',
          '#value' => $form_state->getValue('step2'),
        ];
        $form['step3'] = [
          '#type' => 'fieldset',
          '#title' => $this->t('Step 3: City info'),
        ];
        $form['step3']['city'] = [
          '#type' => 'textfield',
          '#title' => $this->t('Your city'),
          '#default_value' => $form_state->hasValue(['step3', 'city']) ? $form_state->getValue(['step3', 'city']) : '',
          '#required' => TRUE,
        ];
        break;
116
117
118

      default:
        $limit_validation_errors = [];
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
    }

    $form['actions'] = ['#type' => 'actions'];
    if ($form['step']['#value'] > 1) {
      $form['actions']['prev'] = [
        '#type' => 'submit',
        '#value' => $this->t('Previous step'),
        '#limit_validation_errors' => $limit_validation_errors,
        '#submit' => ['::prevSubmit'],
        '#ajax' => [
          'wrapper' => 'ajax-example-wizard-wrapper',
          'callback' => '::prompt',
        ],
      ];
    }
    if ($form['step']['#value'] != 3) {
      $form['actions']['next'] = [
136
137
        '#type' => 'submit',
        '#value' => $this->t('Next step'),
138
        '#submit' => ['::nextSubmit'],
139
        '#ajax' => [
140
          'wrapper' => 'ajax-example-wizard-wrapper',
141
142
143
144
          'callback' => '::prompt',
        ],
      ];
    }
145
146
147
148
149
150
    if ($form['step']['#value'] == 3) {
      $form['actions']['submit'] = [
        '#type' => 'submit',
        '#value' => $this->t("Submit your information"),
      ];
    }
151
152
153
154
155
156
157
158
159

    // This simply allows us to demonstrate no-javascript use without
    // actually turning off javascript in the browser. Removing the #ajax
    // element turns off AJAX behaviors on that element and as a result
    // ajax.js doesn't get loaded.
    // For demonstration only! You don't need this.
    if ($no_js_use) {
      // Remove the #ajax from the above, so ajax.js won't be loaded.
      // For demonstration only.
160
161
      unset($form['actions']['next']['#ajax']);
      unset($form['actions']['prev']['#ajax']);
162
163
    }

164
165
166
    $form['#prefix'] = '<div id="ajax-example-wizard-wrapper">';
    $form['#suffix'] = '</div>';

167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
    return $form;
  }

  /**
   * Wizard callback function.
   *
   * @param array $form
   *   Form API form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   Form API form.
   *
   * @return array
   *   Form array.
   */
  public function prompt(array $form, FormStateInterface $form_state) {
    return $form;
  }

185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
  /**
   * Ajax callback that moves the form to the next step and rebuild the form.
   *
   * @param array $form
   *   The Form API form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The FormState object.
   *
   * @return array
   *   The Form API form.
   */
  public function nextSubmit(array $form, FormStateInterface $form_state) {
    $form_state->setValue('step', $form_state->getValue('step') + 1);
    $form_state->setRebuild();
    return $form;
  }

  /**
   * Ajax callback that moves the form to the previous step.
   *
   * @param array $form
   *   The Form API form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The FormState object.
   *
   * @return array
   *   The Form API form.
   */
  public function prevSubmit(array $form, FormStateInterface $form_state) {
    $form_state->setValue('step', $form_state->getValue('step') - 1);
    $form_state->setRebuild();
    return $form;
  }

219
220
221
222
  /**
   * Save away the current information.
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
223
    $messenger = $this->messenger();
224
225
226
227
    $messenger->addMessage($this->t('Your information has been submitted:'));
    $messenger->addMessage($this->t('Name: @name', ['@name' => $form_state->getValue(['step1', 'name'])]));
    $messenger->addMessage($this->t('Address: @address', ['@address' => $form_state->getValue(['step2', 'address'])]));
    $messenger->addMessage($this->t('City: @city', ['@city' => $form_state->getValue(['step3', 'city'])]));
228
229
230
231

  }

}