テキストフィールドを追加するAdd moreボタンと対応するRemoveボタンを表示したい。
私は ajax_example_add_more()
に従ってこれを達成しましたDrupal 7. 7. Drupal 8コード。
_class XmlfeedsSettingsForm extends FormBase {
public function getFormId() {
return 'formid';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
// Because we have many fields with the same values, we have to set
// #tree to be able to access them.
$form['#tree'] = TRUE;
$form['names_fieldset'] = array(
'#type' => 'fieldset',
'#title' => t('People coming to the picnic'),
// Set up the wrapper so that AJAX will be able to replace the fieldset.
'#prefix' => '<div id="names-fieldset-wrapper">',
'#suffix' => '</div>',
);
// Build the fieldset with the proper number of names. We'll use
// $form_state['num_names'] to determine the number of textfields to build.
$form_state->getValue['num_names_parent'] = '';
if (empty($form_state->getValue['num_names_parent'])) {
$form_state->getValue['num_names_parent'] = 1;
}
for ($i = 0; $i < $form_state->getValue['num_names_parent']; $i++) {
$form['names_fieldset']['name'][$i] = array(
'#type' => 'textfield',
'#title' => t('Name'),
);
}
$form['names_fieldset']['add_name'] = array(
'#type' => 'submit',
'#value' => t('Add one more'),
'#submit' => array('::ajax_example_add_more_add_one'),
// See the examples in ajax_example.module for more details on the
// properties of #ajax.
'#ajax' => array(
'callback' => '::ajax_example_add_more_callback',
'wrapper' => 'names-fieldset-wrapper',
),
);
if ($form_state->getValue['num_names_parent'] > 1) {
$form['names_fieldset']['remove_name'] = array(
'#type' => 'submit',
'#value' => t('Remove one'),
'#submit' => array('::ajax_example_add_more_remove_one'),
'#ajax' => array(
'callback' => '::ajax_example_add_more_callback',
'wrapper' => 'names-fieldset-wrapper',
),
);
}
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Submit'),
);
// 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.
// if (!empty($form['names_fieldset']['remove_name']['#ajax'])) {
// unset($form['names_fieldset']['remove_name']['#ajax']);
// }
// unset($form['names_fieldset']['add_name']['#ajax']);
// }
return $form;
}
public function ajax_example_add_more_add_one(array &$form, FormStateInterface $form_state) {
print_R($form_state);die;
//$form_state->getValue['num_names_parent']++;
//$form_state->setRebuild(TRUE);
}
public function ajax_example_add_more_callback(array &$form, FormStateInterface $form_state) {
return $form['names_fieldset'];
}
public function ajax_example_add_more_remove_one(array &$form, FormStateInterface $form_state) {
if ($form_state->getValue['num_names_parent'] > 1) {
$form_state->getValue['num_names_parent']--;
}
$form_state['rebuild'] = TRUE;
}
_
print_r($form_state)
のbuildForm()
は、以下を出力します。
_[getValue] => Array
(
[num_names_parent] => 1
)
_
ajax_example_add_more_add_one()
には、num_names_parentインデックスがありません。
Add moreボタンを正しく追加するにはどうすればよいですか?
できます !!これを試して
namespace Drupal\fapi_example\Form;
use Drupal\Core\Form\FormStateInterface;
class AjaxAddMore extends DemoBase {
public function buildForm(array $form, FormStateInterface $form_state) {
$form['description'] = array(
'#markup' => '<div>'. t('This example shows an add-more and a remove-last button.').'</div>',
);
$i = 0;
$name_field = $form_state->get('num_names');
$form['#tree'] = TRUE;
$form['names_fieldset'] = [
'#type' => 'fieldset',
'#title' => $this->t('People coming to picnic'),
'#prefix' => '<div id="names-fieldset-wrapper">',
'#suffix' => '</div>',
];
if (empty($name_field)) {
$name_field = $form_state->set('num_names', 1);
}
for ($i = 0; $i < $name_field; $i++) {
$form['names_fieldset']['name'][$i] = [
'#type' => 'textfield',
'#title' => t('Name'),
];
}
$form['actions'] = [
'#type' => 'actions',
];
$form['names_fieldset']['actions']['add_name'] = [
'#type' => 'submit',
'#value' => t('Add one more'),
'#submit' => array('::addOne'),
'#ajax' => [
'callback' => '::addmoreCallback',
'wrapper' => 'names-fieldset-wrapper',
],
];
if ($name_field > 1) {
$form['names_fieldset']['actions']['remove_name'] = [
'#type' => 'submit',
'#value' => t('Remove one'),
'#submit' => array('::removeCallback'),
'#ajax' => [
'callback' => '::addmoreCallback',
'wrapper' => 'names-fieldset-wrapper',
]
];
}
$form_state->setCached(FALSE);
$form['actions']['submit'] = [
'#type' => 'submit',
'#value' => $this->t('Submit'),
];
return $form;
}
public function getFormId() {
return 'fapi_example_ajax_addmore';
}
public function addOne(array &$form, FormStateInterface $form_state) {
$name_field = $form_state->get('num_names');
$add_button = $name_field + 1;
$form_state->set('num_names', $add_button);
$form_state->setRebuild();
}
public function addmoreCallback(array &$form, FormStateInterface $form_state) {
$name_field = $form_state->get('num_names');
return $form['names_fieldset'];
}
public function removeCallback(array &$form, FormStateInterface $form_state) {
$name_field = $form_state->get('num_names');
if ($name_field > 1) {
$remove_button = $name_field - 1;
$form_state->set('num_names', $remove_button);
}
$form_state->setRebuild();
}
public function submitForm(array &$form, FormStateInterface $form_state) {
$values = $form_state->getValue(array('names_fieldset', 'name'));
$output = t('These people are coming to the picnic: @names', array(
'@names' => implode(', ', $values),
)
);
drupal_set_message($output);
}
}
エラーの報告がオンになっている場合、コードShreya Shettyはエラーを返します-Drupal 8 ...の変更に関連している可能性がありますが、intとして使用できないオブジェクトに関連しています。 。修正されたバージョンは次のようになります:
namespace Drupal\dynamic_forms\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
class test3 extends FormBase {
public function buildForm(array $form, FormStateInterface $form_state) {
$form['description'] = array(
'#markup' => '<div>'. t('This example shows an add-more and a remove-last button.').'</div>',
);
$i = 0;
$name_field = $form_state->get('num_names');
$form['#tree'] = TRUE;
$form['names_fieldset'] = [
'#type' => 'fieldset',
'#title' => $this->t('People coming to picnic'),
'#prefix' => '<div id="names-fieldset-wrapper">',
'#suffix' => '</div>',
];
if (empty($name_field)) {
$name_field = $form_state->set('num_names', 1);
}
if ($form_state->get('num_names')>0) {
$value = $form_state->get('num_names');
}
else {
$value=1;
}
for ($i = 0; $i < $value; $i++) {
$form['names_fieldset']['name'][$i] = [
'#type' => 'textfield',
'#title' => t('Name'),
];
}
$form['actions'] = [
'#type' => 'actions',
];
$form['names_fieldset']['actions']['add_name'] = [
'#type' => 'submit',
'#value' => t('Add one more'),
'#submit' => array('::addOne'),
'#ajax' => [
'callback' => '::addmoreCallback',
'wrapper' => 'names-fieldset-wrapper',
],
];
// if ($name_field > 1) {
if ($value > 1) {
$form['names_fieldset']['actions']['remove_name'] = [
'#type' => 'submit',
'#value' => t('Remove one'),
'#submit' => array('::removeCallback'),
'#ajax' => [
'callback' => '::addmoreCallback',
'wrapper' => 'names-fieldset-wrapper',
]
];
}
$form_state->setCached(FALSE);
$form['actions']['submit'] = [
'#type' => 'submit',
'#value' => $this->t('Submit'),
];
return $form;
}
public function getFormId() {
return 'fapi_example_ajax_addmore';
}
public function addOne(array &$form, FormStateInterface $form_state) {
$name_field = $form_state->get('num_names');
$add_button = $name_field + 1;
$form_state->set('num_names', $add_button);
$form_state->setRebuild();
}
public function addmoreCallback(array &$form, FormStateInterface $form_state) {
$name_field = $form_state->get('num_names');
return $form['names_fieldset'];
}
public function removeCallback(array &$form, FormStateInterface $form_state) {
$name_field = $form_state->get('num_names');
if ($name_field > 1) {
$remove_button = $name_field - 1;
$form_state->set('num_names', $remove_button);
}
$form_state->setRebuild();
}
public function submitForm(array &$form, FormStateInterface $form_state) {
$values = $form_state->getValue(array('names_fieldset', 'name'));
$output = t('These people are coming to the picnic: @names', array(
'@names' => implode(', ', $values),
)
);
drupal_set_message($output);
}
}
修正されたバージョンは誰か、特に初心者を助けるかもしれないと思った...元の解決策についてShreyaに感謝を言うことを忘れないでください。
Drupal 8の場合:
namespace Drupal\form_api_example\Form;
use Drupal\Core\Form\FormStateInterface;
/**
* Implements the ajax demo form controller.
*
* This example demonstrates using ajax callbacks to add people's names to a
* list of picnic attendees.
*
* @see \Drupal\Core\Form\FormBase
* @see \Drupal\Core\Form\ConfigFormBase
*/
class AjaxAddMore {
/**
* Form with 'add more' and 'remove' buttons.
*
* This example shows a button to "add more" - add another textfield, and
* the corresponding "remove" button.
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$form['description'] = [
'#type' => 'item',
'#markup' => $this->t('This example shows an add-more and a remove-last button.'),
];
// Gather the number of names in the form already.
$num_names = $form_state->get('num_names');
// We have to ensure that there is at least one name field.
if ($num_names === NULL) {
$name_field = $form_state->set('num_names', 1);
$num_names = 1;
}
$form['#tree'] = TRUE;
$form['names_fieldset'] = [
'#type' => 'fieldset',
'#title' => $this->t('People coming to picnic'),
'#prefix' => '<div id="names-fieldset-wrapper">',
'#suffix' => '</div>',
];
for ($i = 0; $i < $num_names; $i++) {
$form['names_fieldset']['name'][$i] = [
'#type' => 'textfield',
'#title' => $this->t('Name'),
];
}
$form['names_fieldset']['actions'] = [
'#type' => 'actions',
];
$form['names_fieldset']['actions']['add_name'] = [
'#type' => 'submit',
'#value' => $this->t('Add one more'),
'#submit' => ['::addOne'],
'#ajax' => [
'callback' => '::addmoreCallback',
'wrapper' => 'names-fieldset-wrapper',
],
];
// If there is more than one name, add the remove button.
if ($num_names > 1) {
$form['names_fieldset']['actions']['remove_name'] = [
'#type' => 'submit',
'#value' => $this->t('Remove one'),
'#submit' => ['::removeCallback'],
'#ajax' => [
'callback' => '::addmoreCallback',
'wrapper' => 'names-fieldset-wrapper',
],
];
}
$form['actions']['submit'] = [
'#type' => 'submit',
'#value' => $this->t('Submit'),
];
return $form;
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'form_api_example_ajax_addmore';
}
/**
* Callback for both ajax-enabled buttons.
*
* Selects and returns the fieldset with the names in it.
*/
public function addmoreCallback(array &$form, FormStateInterface $form_state) {
return $form['names_fieldset'];
}
/**
* Submit handler for the "add-one-more" button.
*
* Increments the max counter and causes a rebuild.
*/
public function addOne(array &$form, FormStateInterface $form_state) {
$name_field = $form_state->get('num_names');
$add_button = $name_field + 1;
$form_state->set('num_names', $add_button);
// Since our buildForm() method relies on the value of 'num_names' to
// generate 'name' form elements, we have to tell the form to rebuild. If we
// don't do this, the form builder will not call buildForm().
$form_state->setRebuild();
}
/**
* Submit handler for the "remove one" button.
*
* Decrements the max counter and causes a form rebuild.
*/
public function removeCallback(array &$form, FormStateInterface $form_state) {
$name_field = $form_state->get('num_names');
if ($name_field > 1) {
$remove_button = $name_field - 1;
$form_state->set('num_names', $remove_button);
}
// Since our buildForm() method relies on the value of 'num_names' to
// generate 'name' form elements, we have to tell the form to rebuild. If we
// don't do this, the form builder will not call buildForm().
$form_state->setRebuild();
}
/**
* Final submit handler.
*
* Reports what values were finally set.
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$values = $form_state->getValue(['names_fieldset', 'name']);
$output = $this->t('These people are coming to the picnic: @names', [
'@names' => implode(', ', $values),
]
);
$this->messenger()->addMessage($output);
}
}
別の解決策($ form_stateのsetメソッドの戻り値に依存する代わりにgetメソッドを使用):
if (empty($name_field)) {
$form_state->set('num_names', 1);
}
$name_field = $form_state->get('num_names');
for ($i = 0; $i < $name_field; $i++) {
$form['names_fieldset']['name'][$i] = [
'#type' => 'textfield',
'#title' => t('Name'),
];
}