Drupal 8在ajax回调后添加ajax表单元素

时间:2017-01-02 10:27:05

标签: ajax forms drupal drupal-8

我正在构建一个带有多个启用了ajax的表单元素的drupal表单。

我有一个选择列表,在更改后执行ajax回调。问题是它为页面添加了一个新的选择列表,也是启用了ajax。这似乎不起作用,这对我来说似乎是合乎逻辑的,因为ajax实际上已捆绑添加到页面中,因此它在replacecommand中丢失。

有没有人有这方面的经验,有没有人有解决方案?

这是我的代码

  /**
     * {@inheritdoc}
     */
    public function buildForm(array $form, FormStateInterface $form_state)
    {
        $form['city'] = [
            '#type' => 'select',
            '#title' => $this->t('Station'),
            '#description' => $this->t('City'),
            '#options' => array(
                'Aalst' => $this->t('Aalst'),
                'Brussel' => $this->t('Brussel'),
                'Hasselt' => $this->t('Hasselt'),
                'Leuven' => $this->t('Leuven'),
            ),
            '#ajax' => [
                'callback' => array($this, 'extendFormAjax'),
                'event' => 'change',
                'progress' => array(
                    'type' => 'throbber',
                    'message' => t('Choose City'),
                ),
            ],
            '#suffix' => '<div id="extended-form"></div>',
        ];

        $form['submit'] = [
            '#type' => 'submit',
            '#value' => t('Submit'),
        ];

        return $form;
    }

    /**
     * Ajax callback to validate the email field.
     */
    public function extendFormAjax(array &$form, FormStateInterface $form_state)
    {
        $parking = [
            '#type' => 'select',
            '#title' => $this->t('Parking'),
            '#description' => $this->t('Parking'),
            '#options' => [
                'P1' => $this->t('P1'),
                'P2' => $this->t('P2'),
            ],
            '#ajax' => [
                'callback' => array($this, 'extendFormAjax'),
                'event' => 'change',
                'progress' => array(
                    'type' => 'throbber',
                    'message' => t('Choose parking'),
                ),
            ],
        ];

        $response = new AjaxResponse();
        $response->addCommand(new InsertCommand('#extended-form', $parking));

        return $response;
    }

4 个答案:

答案 0 :(得分:1)

尝试在JS Drupal.attachBehaviors();

中调用某个地方

答案 1 :(得分:1)

我有一个类似的问题,我通过在buildForm中添加元素并为其添加包装并通过HtmlCommand发送表单元素来解决它

  /**
 * {@inheritdoc}
 */
public function buildForm(array $form, FormStateInterface $form_state)
{
    $form['city'] = [
        '#type' => 'select',
        '#title' => $this->t('Station'),
        '#description' => $this->t('City'),
        '#options' => array(
            'Aalst' => $this->t('Aalst'),
            'Brussel' => $this->t('Brussel'),
            'Hasselt' => $this->t('Hasselt'),
            'Leuven' => $this->t('Leuven'),
        ),
        '#ajax' => [
            'callback' => array($this, 'extendFormAjax'),
            'event' => 'change',
            'progress' => array(
                'type' => 'throbber',
                'message' => t('Choose City'),
            ),
        ],
    ];
     $form['parking'] = [
        '#prefix' => '<div id="extended-form">',
        '#suffix' => '</div>',
        '#type' => 'select',
        '#title' => $this->t('Parking'),
        '#description' => $this->t('Parking'),
        '#options' => [
            'P1' => $this->t('P1'),
            'P2' => $this->t('P2'),
        ],
        '#ajax' => [
            'callback' => array($this, 'extendFormAjax'),
            'event' => 'change',
            'progress' => array(
                'type' => 'throbber',
                'message' => t('Choose parking'),
            ),
        ],
    ];

    $form['submit'] = [
        '#type' => 'submit',
        '#value' => t('Submit'),
    ];

    return $form;
}

/**
 * Ajax callback to validate the email field.
 */
public function extendFormAjax(array &$form, FormStateInterface $form_state)
{
    $parking = [
        '#type' => 'select',
        '#title' => $this->t('Parking'),
        '#description' => $this->t('Parking'),
        '#options' => [
            'P1' => $this->t('P1'),
            'P2' => $this->t('P2'),
        ],
        '#ajax' => [
            'callback' => array($this, 'extendFormAjax'),
            'event' => 'change',
            'progress' => array(
                'type' => 'throbber',
                'message' => t('Choose parking'),
            ),
        ],
    ];

    $response = new AjaxResponse();
    $response->addCommand(new HtmlCommand('#extended-form', $parking));

    return $response;
}

试试这样。我还没有测试过代码。

答案 2 :(得分:0)

您需要在buildForm方法中添加ajax元素并重建表单。像这样:

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

    // We want to deal with hierarchical form values.
    $form['#tree'] = TRUE;

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

    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;
      case 2:
        $limit_validation_errors = [['step'], ['step1']];
        $form['step1'] = [
          '#type' => 'value',
          '#value' => $form_state->getValue('step1'),
        ];
        $form['step2'] = [
          '#type' => 'fieldset',
          '#title' => t('Step 2: Street address info'),
        ];
        $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;
    }

    $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'] = [
        '#type' => 'submit',
        '#value' => $this->t('Next step'),
        '#submit' => ['::nextSubmit'],
        '#ajax' => [
          'wrapper' => 'ajax-example-wizard-wrapper',
          'callback' => '::prompt',
        ],
      ];
    }
    if ($form['step']['#value'] == 3) {
      $form['actions']['submit'] = [
        '#type' => 'submit',
        '#value' => $this->t("Submit your information"),
      ];
    }

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

    return $form;
  }

  public function prompt(array $form, FormStateInterface $form_state) {
    return $form;
  }

  public function nextSubmit(array $form, FormStateInterface $form_state) {
    $form_state->setValue('step', $form_state->getValue('step') + 1);
    $form_state->setRebuild();
    return $form;
  }

  public function prevSubmit(array $form, FormStateInterface $form_state) {
    $form_state->setValue('step', $form_state->getValue('step') - 1);
    $form_state->setRebuild();
    return $form;
  }

  public function submitForm(array &$form, FormStateInterface $form_state) {
    $messenger = \Drupal::messenger();
    $messenger->addMessage($this->t('Your information has been submitted:'));
  }

答案 3 :(得分:0)

我遇到了这个问题,并通过以下方式解决了这个问题: 对于由Ajax填充的每个元素,我添加属性“ #validated” => true,然后在回调中,返回的字段必须具有与原始字段相同的属性(id,名称):

$form['example_field'] = array(
        '#type'         => 'select',
        '#required'     => FALSE,
        '#options'      => getDynamicOptions(),
        '#prefix'       => '<div id="etablissement-type-wrapper">',
        '#suffix'       => '</div>',
        '#attributes'   => [
            'data-drupal-selector'  =>  "edit-example",
            'id'    =>  "edit-example",
            'name'  =>  "example",
        ],
        '#validated' => TRUE,
    );