AJAX以前にAJAXによってレンダリングされたフォーム要素へのコールバックを追加しましたが、うまくいきませんでした。以下のコードを追加します。
少し説明。ここには3つの主要な方法があります。
buildForm
-基本フォームextraField
-AJAXに添付されたコールバック['month']
choosePerson
-AJAXコールバックが添付されている:['week_day']['hour']
BuildFormメソッドで、AJAX 'month' select要素のコールバックを使用して基本フォームを作成します。AJAXコールバックで、extraFieldメソッドを見つけることができます。このメソッドには、 「時間」と呼ばれるフォーム要素($form['week_day']['hour']
)この要素は適切にレンダリングされます。ただし、この要素にはAJAXコールバックも含まれます。これは機能しません。「person_container」要素と「person」選択は生成されません。
以前にajaxによってレンダリングされた要素をajax化する方法はありますか?
class ReservationForm extends FormBase {
public function getFormId() {
return 'reservation_form';
}
public function buildForm(array $form, FormStateInterface $form_state) {
$form['month'] = array(
'#type' => 'select',
'#title' => $this->t('Select month'),
'#options' => array($this->t('January'), $this->t('February'), $this->t('March')),
'#ajax' => array(
'callback' => array($this, 'extraField'),
'event' => 'change',
'wrapper' => 'week-day',
),
);
// Disable caching on this form.
$form_state->setCached(FALSE);
$form['week_day'] = [
'#type' => 'container',
'#attributes' => ['id' => 'week-day'],
];
}
public function extraField(array &$form, FormStateInterface $form_state) {
$month = $form_state->getValue('month');
$hour_options = array();
if ($month == '0') {
$hour_options[0] = $this->t('08:00');
$hour_options[1] = $this->t('09:00');
$hour_options[2] = $this->t('10:00');
}
if ($month == '1') {
$hour_options[0] = $this->t('12:00');
$hour_options[1] = $this->t('13:00');
$hour_options[2] = $this->t('14:00');
}
if ($month == '2') {
$hour_options[0] = $this->t('18:00');
$hour_options[1] = $this->t('19:00');
$hour_options[2] = $this->t('20:00');
}
$form['week_day']['hour'] = array(
'#type' => 'select',
'#title' => $this->t('Choose hours @month', array('@month' => $month)),
'#options' => $hour_options,
'#ajax' => array(
// tried with that callback too: [ $this, 'choosePerson']
'callback' => array($this, 'choosePerson'),
'event' => 'change',
'wrapper' => 'person',
),
);
$form['week_day']['person_container'] = array(
'#type' => 'container',
'#attributes' => ['id' => 'person-container'],
);
$form['week_day']['person_container']['person'] = array(
'#type' => 'select',
'#title' => $this->t('Choose person'),
'#options' => ['John', 'Sarah', 'Peter'],
);
return $form['week_day'];
}
public function choosePerson(array &$form, FormStateInterface $form_state) {
$form['week_day']['person_container']['person'] = array(
'#type' => 'select',
'#title' => $this->t('Choose person'),
'#options' => ['John', 'Sarah', 'Peter'],
);
return $form['week_day']['person_container'];
}
}
質問のディスカッションに投稿された Link 4k4が解決策を提供します。
コールバック関数(#ajax ['callback']という名前)を作成します。これは一般に非常に単純な関数で、元のページで置き換えられるフォームの部分を選択して返すだけです。フォームAPIセキュリティシステムの一部として、送信時にエラーがスローされ、コールバックで作成された要素の#ajaxも機能しないため、コールバック関数で新しいフォーム要素を作成できないことに注意してください。 ajax submitで新しい要素を作成する必要がある場合、それらをフォーム定義に追加する必要があります。$ form_stateの値を使用して、フォームビルドプロセスは、最初のフォームロード、または#ajaxによって開始されるロードです。
したがって、次のコード例は機能しています。
class ReservationForm extends FormBase {
public function getFormId() {
return 'reservation_form';
}
public function buildForm(array $form, FormStateInterface $form_state) {
$form['month'] = [
'#type' => 'select',
'#title' => $this->t('Select month'),
'#options' => [
$this->t('January'),
$this->t('February'),
$this->t('March'),
],
'#ajax' => [
'callback' => [$this, 'extraField'],
'event' => 'change',
'wrapper' => 'week-day',
],
];
// Disable caching on this form.
$form_state->setCached(FALSE);
$form['week_day'] = [
'#type' => 'container',
'#attributes' => ['id' => 'week-day'],
];
if ($form_state->getUserInput()['_triggering_element_name'] == 'month') {
$month = $form_state->getValue('month');
$hour_options = [];
if ($month == '0') {
$hour_options[0] = $this->t('08:00');
$hour_options[1] = $this->t('09:00');
$hour_options[2] = $this->t('10:00');
}
if ($month == '1') {
$hour_options[0] = $this->t('12:00');
$hour_options[1] = $this->t('13:00');
$hour_options[2] = $this->t('14:00');
}
if ($month == '2') {
$hour_options[0] = $this->t('18:00');
$hour_options[1] = $this->t('19:00');
$hour_options[2] = $this->t('20:00');
}
$form['week_day']['hour'] = [
'#type' => 'select',
'#title' => $this->t('Choose hours @month', ['@month' => $month]),
'#options' => $hour_options,
'#ajax' => [
'callback' => [$this, 'choosePerson'],
'event' => 'change',
'wrapper' => 'person-container',
],
];
$form['week_day']['person_container'] = [
'#type' => 'container',
'#attributes' => ['id' => 'person-container'],
];
$form['week_day']['person_container']['person'] = [
'#type' => 'select',
'#title' => $this->t('Choose person'),
'#options' => ['John', 'Sarah', 'Peter'],
];
}
if ($form_state->getUserInput()['_triggering_element_name'] == 'hour') {
$form['week_day']['person_container']['person'] = [
'#type' => 'select',
'#title' => $this->t('Choose person'),
'#options' => ['Hans', 'Frank', 'Emma'],
];
}
return $form;
}
public function submitForm(array &$form, FormStateInterface $form_state) {
}
public function extraField(array &$form, FormStateInterface $form_state) {
return $form['week_day'];
}
public function choosePerson(array &$form, FormStateInterface $form_state) {
return $form['week_day']['person_container'];
}
}
コールバックまたはvalidateForm()で要素を変更することはできません。buildForm()メソッドに配置する必要があります。
ここに完全な例があります:
/method buildForm
$result = \Drupal\my_module\Controller\Contaminante::list(); //database logic
foreach ($result as $it){
$arrSelectContaminantes[$it["id_contaminante"]] = t($it["descripcion"]);
}
$form['select_contaminantes'] = array(
'#type' => 'select',
'#options' => $arrSelectContaminantes,
'#ajax' => [
'callback' => '::seleccionContaminantes',
'disable-refocus' => false,
'event' => 'change',
'wrapper' => 'el-select-estaciones',
'method' => 'replaceWith'
]
);
$selected_value = $form_state->getValue('select_contaminantes');
$opciones = array();
if(isset(selected_value)){
$resultado;
if($form_state->getValue("select_contaminantes") != 0){
$opciones["0"] = t("ALL");
$resultado = \Drupal\montar_mapa\Controller\Estacion::lista($form_state->getValue("select_contaminantes")); //DB LOGIC
}else{
$resultado = \Drupal\montar_mapa\Controller\Estacion::lista(); //DB LOGIC
}
foreach ($resultado as $it){
$opciones[$it["id"]] = t($it["nombre"]);
}
}
$form['select_estaciones'] = array(
'#type' => 'select',
'#id' => "el-select-estaciones",
'#options' => $opciones,
'#empty_option' => $this->t('-Select contaminante first'),
'#validated' => TRUE,
);
本当に重要:
依存フィールド(例では$ form ['select_estaciones')を印刷するたびに、検証する必要があります(オプションで '#validated' => TRUE)
Nullであるかどうかにかかわらず、トリガーフィールド(例では$ form ['select_contaminante])の選択した値を比較する必要があります。直接比較すると、値が0の場合、「選択なし」と解釈されます。