programmatically-created - "two dimentionnal ' 的问题添加另一个项目'"with FormStateInterface::getTriggeringElement()

标签 programmatically-created drupal-forms drupal-8 drupal-ajax

我正在学习 drupal 8。我想创建一个包含“二维”“添加另一个项目”表单的页面。我的代码几乎运行良好,但是当我向房子添加房间时我有一个奇怪的行为(FormStateInterface::getTriggeringElement() 的调试日志中有一个奇怪的值,请参阅底部的代码和日志)

第一:我有两个结构,房子和房间。用户可以创建一些房屋,对于每个房屋,他可以创建一些房间:

enter image description here

当我添加一些房屋时,表格工作正常:

enter image description here

当我向最后一栋房子添加一些房间时,表格也可以正常工作:

enter image description here

但是当我将一些房间添加到任何“no-last”房子时,表单无法正常工作(在屏幕截图中,我单击一次到“1”块房子中的“添加房间”,“房子 1”变成了“房子 2”(?!),然后点击添加 5 个房间(?!):

enter image description here

这里我的代码和一个奇怪的调试日志,我没有解释为什么我得到这个值(来自 room_addMoreSubmit 回调中的 getTriggeringElement() ,这是我认为的问题)

<?php

namespace Drupal\projet\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;

class HouseForm extends FormBase {

  public function getFormId(){
    return 'custom_rooms_form';
  }

  function buildForm(array $form, FormStateInterface $form_state) {



    $house_count = $form_state->get('house_count');

    if (is_null($house_count)) {
      $house_count = 1;
      $form_state->set('house_count', $house_count);
    }

    $form['house'] = array(
        //'#tree' => TRUE,
        '#prefix' => '<div id="house-replace">',
        '#suffix' => '</div>'
    );

    for ($house_delta = 0; $house_delta < $house_count; $house_delta++) {
      if (!isset($form['house'][$house_delta])) {

        $room_count[$house_delta] = $form_state->get('room_count_'.$house_delta);

        if (is_null($room_count[$house_delta])) {
          $room_count[$house_delta] = 1;
          $form_state->set('room_count_'.$house_delta, $room_count[$house_delta]);
        }

        dd($room_count, "room_COUNT");

        $form['house'][$house_delta]['room'] = array(
            '#type' => 'fieldset',
            '#title' => t('house : '.$house_delta),
            //'#tree' => TRUE,
            '#prefix' => '<div id="room-replace-'.$house_delta.'">',
            '#suffix' => '</div>'
        );

        for ($room_delta = 0; $room_delta < $room_count[$house_delta]; $room_delta++) {
          if (!isset($form['house'][$house_delta]['room'][$room_delta])) {
            $room = array(
                '#type' => 'textfield'
            );
            $check = array(
                '#type' => 'checkbox'
            );
            $form['house'][$house_delta]['room'][$room_delta] = array(
                '#type' => 'fieldset',
                '#title' => t('room : '.$house_delta.'.'.$room_delta),
            );
            $form['house'][$house_delta]['room'][$room_delta]['text'] = $room;
            $form['house'][$house_delta]['room'][$room_delta]['check'] = $check;
          }
        }

        $form['house'][$house_delta]['room']['add'] = array(
            '#type' => 'submit',
            '#name' => 'add',
            '#value' => t('Add room'),
            '#attributes' => array('class' => array('field-add-more-submit'), 'house_delta' => array($house_delta)),
            '#submit' => array(array(get_class($this), 'room_addMoreSubmit')),
            '#ajax' => array(
                'callback' => array($this, 'room_addMoreCallback'),
                'wrapper' => 'room-replace-'.$house_delta,
                'effect' => 'fade',
            ),
        );

      }
    }

    $form['house']['add'] = array(
        '#type' => 'submit',
        '#name' => 'add',
        '#value' => t('Add house'),
        '#attributes' => array('class' => array('field-add-more-submit')),
        '#submit' => array(array(get_class($this), 'house_addMoreSubmit')),
        '#ajax' => array(
            'callback' => array($this, 'house_addMoreCallback'),
            'wrapper' => 'house-replace',
            'effect' => 'fade',
        ),
    );


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

    return $form;
  }

  public function room_addMoreSubmit(array $form, FormStateInterface $form_state) {
    dd($form_state->getTriggeringElement(), "room : getTriggeringElement()"); // below, the log when I add a room to the house '1' (result see above  with the last screenshot: "the house 1" became "house 2" and one click add 5 rooms)
    $house = $form_state->getTriggeringElement()["#array_parents"][1];
    $c = $form_state->get('room_count_'.$house) + 1;
    $form_state->set('room_count_'.$house, $c);
    $form_state->setRebuild(TRUE);
  }

  public function room_addMoreCallback(array $form, FormStateInterface $form_state) {
    $house = $form_state->getTriggeringElement()["#array_parents"][1];
    return $form['house'][$house]['room'];
  }

  public function house_addMoreSubmit(array $form, FormStateInterface $form_state) {
    dd($form_state->getTriggeringElement()["#array_parents"], "house : getTriggeringElement()"); 
    $c = $form_state->get('house_count') + 1;
    $form_state->set('house_count', $c);
    $form_state->setRebuild(TRUE);
  }

  public function house_addMoreCallback(array $form, FormStateInterface $form_state) {
    return $form['house'];
  }

}

单击房屋“1”中的“添加房间”按钮时的日志(room_addMoreSubmit 中的“dd”):

enter image description here

当我点击门牌号 1 中的“添加房间”按钮时,getTriggeringElement 返回添加按钮的数组父项。而且,正如你所看到的, parent 是“2”而不是“1”(房子1)
所以当我点击房子 1 的“添加房间”按钮时,这是被识别的房子“2”而不是房子“1”。

我不明白为什么...使用 getTriggeringElement 不是好方法?

最佳答案

解决方案 :

$form['house'][$house_delta]['room']['add'] = array(
            '#type' => 'submit',
            '#name' => 'add-'.$house_delta,
            '#value' => t('Add room'),
            '#attributes' => array('class' => array('field-add-more-submit'), 'house_delta' => array($house_delta)),
            '#submit' => array(array(get_class($this), 'room_addMoreSubmit')),
            '#ajax' => array(
                'callback' => array($this, 'room_addMoreCallback'),
                'wrapper' => 'room-replace-'.$house_delta,
                'effect' => 'fade',
            ),
        );

唯一的名称是我的问题的问题。所以,我更改了 name 属性。

关于programmatically-created - "two dimentionnal ' 的问题添加另一个项目'"with FormStateInterface::getTriggeringElement(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33418479/

相关文章:

Drupal 7 - 在#link 表单类型条目中添加 HTML?

drupal - 如何将自定义表单添加到自定义模块中的自定义 block

jQuery - Ajax 选择选项 Drupal 自定义表单 'POST Error 500'

php - 将 drupal 7 完整内容类型迁移到 drupal 8

csv - Drupal 8 - 从具有多个值的 CSV 迁移图像字段

ios - 程序化 UITableView 中不显示节标题

ios - 如何以编程方式填充 switch case 值?

swift - 处于编辑模式时的 UITableViewCell 宽度问题

ios - 设置no storyboard后不调用viewDidLoad

entity - 在某些情况下删除实体 Drupal 8