web-dev-qa-db-ja.com

フォームにフィールドを動的に追加する

やあ、

ユーザー名を入力できるフォームを作成しようとしています。ボタンを押して動的に新しいテキストフィールドを追加したい。私は 次の質問 にもとづいてコードを作成しました(drupal 8も使用しており、おそらく機能するはずなので)。

ただし、残念ながらフィールドは追加されません。現在使用しているコードは次のようになります。

<?php
    /**
     * @file
     * Contains \Drupal\bulk_email\Form\EmailForm.
     */

    namespace Drupal\bulk_email\Form;
    use Drupal\Core\Form\FormBase;
    use Drupal\Core\Form\FormStateInterface;
    use Drupal\Component\Utility\UrlHelper;

    class EmailForm extends FormBase {
        public function getFormId() {
            return "bulk_email_form";
        }

        public function buildForm(array $form, FormStateInterface $form_state) {
            $form['#tree'] = TRUE;

            $form['users'] = array(
              '#type' => 'fieldset',
              '#title' => t('Users'),
              '#prefix' => '<div id="users-wrapper">',
              '#suffix' => '</div>',
            );

            $num_users = $form_state->getValue('num_users');
            if (empty($num_users)) {
                $num_users = 1;
            }
            for ($i = 0; $i < $num_users; $i++) {
                $form['users'][$i] = array(
                    '#type'  => 'textfield',
                    '#description' => t('Select a user.'),
                );
            }

            $form['users']['users_more'] = array(
                '#type' => 'submit',
                '#value' => t('Add one'),
                '#submit' => array($this, 'bulk_email_addfieldsubmit'),
                '#ajax' => array(
                     'callback' => array($this, 'bulk_email_add_more_callback'),
                     'wrapper' => 'users-wrapper',
                ),
            );

            $form['actions'] = array('#type' => 'actions');
            $form['submit'] = array(
                '#type' => 'submit',
                '#value' => t('Send'),
            );
            return $form;
        }

        public function submitForm(array &$form, FormStateInterface $form_state) {
            // submit code
        }

        public function bulk_email_addfieldsubmit(array &$form, FormStateInterface $form_state) {
            $num_users = $form_state->get('num_users') + 1;
            $form_state->set('num_users', $num_users);
            $form_state->setRebuild(TRUE);
        }

        public function bulk_email_add_more_callback(array &$form, FormStateInterface $form_state) {
            return $form['users'];
        }
    }
?>

細かい部分が欠けている可能性が高いですが、見つからないようです...どんな助けでもありがたいです。

敬具。

2

私は間違っているかもしれませんが、bulk_email_add_more_callbackが実際には呼び出されないと想定して、ajaxコールバックをに変更してみることもできます。

'#ajax' => array(
                 'callback' => '::bulk_email_add_more_callback',
                 'wrapper' => 'users-wrapper',
            ),

そして、実際のコールバックで、completeformから値を取得します。これが私の問題でした。すべての値が正しいのですが、古い値を返しました。

public function bulk_email_add_more_callback(array &$form, FormStateInterface $form_state) {
        $form = $form_state->getCompleteForm()
        return $form['users'];
    }
1
Johann

私は自分の問題に対する解決策を見つけられず、それが設計上の悪い決定なのかバグなのか疑問に思い始めました。

とにかく、他のユーザーのために、私は次の回避策を使用しました:

まず、これらの余分なフィールドを追加するときにすべてのコードを削除しました。ユーザー名を入力する実際のテキストフィールドのみを残しました。次に、user-collectionという新しい非表示フィールドを追加しました。

残りは、カスタムJavaScriptを追加することによって行われました。このスクリプトは、(オートコンプリートに基づいて)ユーザー名が入力されたかどうかを検出します。次に「;」を追加しますuser-collectionの値に。次に、テキストフィールドをクリアします。結果は、入力されたすべてのユーザー名を含むユーザーコレクションフィールドです。最後に、ユーザーの収集の内容を示す視覚的なフィードバックも追加しました(解析後)。

それは回避策であり、私にもかなりの努力を要しましたが、何もしないよりはましです。

1

Ajaxリクエストで送信が呼び出されるかどうかを確認しましたか?

_public function bulk_email_addfieldsubmit(array &$form, FormStateInterface $form_state) {
    $num_users = $form_state->get('num_users') + 1;
    $form_state->set('num_users', $num_users);
_

そうでない場合は、このコードをbuildForm()に配置できます。この場合、トリガー要素が正しいかどうかを確認する必要があります。

もう1つの小さな問題、buildForm()のこの行:

_$num_users = $form_state->getValue('num_users');
_

get('num_users')はユーザー入力用であるため、getValue()にする必要があります。

1
4k4

このようなものを使用できます。

if (!empty($form_state['values']['field_name'])) {
    $form[]=array();//add your form elements to be shown after submit.
}
else {
    $form[]=array();//here your original form.
}
return $form;

フォームに追加を送信

$form_State['rebuild']=true;
1
ana

私も同じシナリオです。 drupal 8.でajaxを使用して、テキストフィールドを動的に正常に追加および削除できます。私は以下のコードを添付しました。実際に、サンプルのfapiモジュールに従って、add moreフォームを使用していると思いますか?

fapiに問題があり、drupal 8.にフォームを追加します。パッチもそこにあります。自分でシナリオのコードを修正しました。

最初のステップ: formstate変数のロジックの背後で作業しています。フィールドを動的に加算または減算するformstate変数の値。

最初にフォーム関数を作成するときは$ form ['#tree'] = TRUE;プロパティを設定する必要があります。次に、送信関数で適切な送信値を取得できるのはあなただけです。

 $veritas_id = $form_state->get('veritas_id');
if ($veritas_id === NULL) {
  $veritas_id = $form_state->set('veritas_id', 0);
  $veritas_id = 0;
  }

2番目のステップ

$form['veritasIds'] = [
  '#type' => 'fieldset',
  //'#title' => $this->t('#ID'),
  '#prefix' => '<div id="veritas-id-wrapper">',
  '#suffix' => '</div>',
  ];



  $form['veritasIds']['actions']['add_name'] = [
  '#type' => 'submit',
  '#limit_validation_errors' => array(),
  '#value' => t('add row'),
  //'#name'=>$veritas,
  '#submit' => array('::addOneVeritas'),
  '#ajax' => [
  'callback' => '::addmoreCallbackVeritas',
  'wrapper' => 'veritas-id-wrapper',
  ],

  '#attributes' => array('class'=> array('btn-transparent')),
  ];

  //if ($num_names > 1) {

  $form['veritasIds']['actions']['remove_name'] = [
  '#type' => 'submit',
  '#limit_validation_errors' => array(),
  '#value' => t('delete row'),
  '#submit' => array('::removeoneVeritas'),
  '#ajax' => [
    'callback' => '::addmoreCallbackVeritas',
    'wrapper' => 'veritas-id-wrapper',
  ],
  '#name'=>t('veritasremove'),

  '#attributes' => array('class'=> array('btn-transparent')),
  '#suffix' => t('<div class="id-wrapper">#ID</div>'),
  ];

  for ($i = 0; $i < $veritas_id; $i++) {
  $form['veritasIds']['id'][$i] = [
  '#type' => 'textfield',
  '#attributes' => array('class'=> array('veritas-addfield')),
  //'#title' => t('Name'),
  ];
  }

ここで作成されたフィールドセットです。フィールドセット内では、行を追加してボタンを削除するだけで、追加された動的フィールドがそこにあります。

番目のステップ $ form_state-> setCached(FALSE);送信が必要であり、ajaxコールバック関数は

public function addmoreCallbackVeritas(array &$form, FormStateInterface $form_state) {
  $veritas_id = $form_state->get('veritas_id');
  return $form['veritasIds'];

}

public function addOneVeritas(array &$form, FormStateInterface $form_state) {
    $veritas_id = $form_state->get('veritas_id');
    $add_button1 = $veritas_id + 1;
    $form_state->set('veritas_id', $add_button1);
    $form_state->setRebuild();
  }

これについて疑問があれば遠慮なく尋ねてください

1
Vinodhini