"two dimentionnal 'add another item' " 与 FormStateInterface::getTriggeringElement() 的问题
Issue for a "two dimentionnal 'add another item' " with FormStateInterface::getTriggeringElement()
我正在学习 drupal 8。我想创建一个包含 'two dimensionnal' 'add another item' 表单的页面。我的代码几乎运行良好,但是当我向房子添加房间时我有一个奇怪的行为(我的调试日志中有一个奇怪的值来自 FormStateInterface::getTriggeringElement(),请参阅底部的代码和日志)
首先:我有两个结构,房子和房间。用户可以创建一些房子,对于每个房子,他可以创建一些房间:
当我添加一些房子时,表格工作正常:
当我向最后一栋房子添加一些房间时,表格也能正常工作:
但是,当我向任何 "no-last" 房屋添加一些房间时,该表格无法正常工作(在屏幕截图中,我单击了一次方块房屋 '1' 中的 "add room" , "house 1" 的标签变为 "house 2" (?!) 点击添加 5 个房间 (?!) :
这是我的代码和一个奇怪的调试日志,我没有解释为什么我得到这个值(来自 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”中的"add room"按钮时的日志('dd'在room_addMoreSubmit):
当我点击1号门牌的"add room"按钮时,getTriggeringElementreturn添加按钮的数组parents。而且,如您所见,parent 是“2”而不是“1”(房子 1)
因此,当我单击房屋 1 的 "add room" 按钮时,识别的是房屋“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',
),
);
唯一名称是我的问题所在。所以,我更改了名称属性。
我正在学习 drupal 8。我想创建一个包含 'two dimensionnal' 'add another item' 表单的页面。我的代码几乎运行良好,但是当我向房子添加房间时我有一个奇怪的行为(我的调试日志中有一个奇怪的值来自 FormStateInterface::getTriggeringElement(),请参阅底部的代码和日志)
首先:我有两个结构,房子和房间。用户可以创建一些房子,对于每个房子,他可以创建一些房间:
当我添加一些房子时,表格工作正常:
当我向最后一栋房子添加一些房间时,表格也能正常工作:
但是,当我向任何 "no-last" 房屋添加一些房间时,该表格无法正常工作(在屏幕截图中,我单击了一次方块房屋 '1' 中的 "add room" , "house 1" 的标签变为 "house 2" (?!) 点击添加 5 个房间 (?!) :
这是我的代码和一个奇怪的调试日志,我没有解释为什么我得到这个值(来自 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”中的"add room"按钮时的日志('dd'在room_addMoreSubmit):
当我点击1号门牌的"add room"按钮时,getTriggeringElementreturn添加按钮的数组parents。而且,如您所见,parent 是“2”而不是“1”(房子 1) 因此,当我单击房屋 1 的 "add room" 按钮时,识别的是房屋“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',
),
);
唯一名称是我的问题所在。所以,我更改了名称属性。