Cara membangun kembali formulir setelah panggilan AJAX


12

Saya mencoba untuk mengizinkan pengguna untuk secara dinamis memilih sejumlah bidang berdasarkan pada kotak dropdown menggunakan panggilan ajax, tapi saya sepertinya tidak bisa mendapatkan panggilan ajax untuk membangun kembali formulir sesudahnya.

<?php
class AJAXexample extends BlockBase {
    public function blockForm($form, FormStateInterface $form_state) {
        if (empty($form_state->getValue('number'))) {
            $form_state->setValue('number', 3);
        } 
        $form['columnNum'] = [
            '#title'   => t('Number of Columns'),
            '#type'    => 'select',
            '#options' => [
                1         => '1',
                2         => '2',
                3         => '3',
                4         => '4',
            ],
            '#default_value' => $this->configuration['columnNum'],
            '#empty_option'  => t('-select-'),
            '#ajax'          => [
                'callback'      => [$this, 'columnCallback'],
            ],
        ];
        for ($i = 0; $i < $form_state->getValue('number'); $i += 1) {
            $form['column'][$i] = [
                $i => [
                    '#type'       => 'details',
                    '#title'      => t('Column '.$numTitle),
                    '#open'       => FALSE,
                    'columnTitle' => [
                        '#type'      => 'textfield',
                        '#title'     => t('Column Title'),
                        '#value'     => $config[0]['columnTitle'],
                    ],  
                ],
            ];  
        return $form;
    }

    public function columnCallback(array &$form, FormStateInterface $form_state) {
        $form_state->setValue('number', 10);
        $form_state->setRebuild(true);
        return $form;
    }
}

Jumlah bidang teks didasarkan pada variabel 'angka' form_state. Callback columnCallback mengubah variabel form_state menjadi 10, dan dipecat ketika bidang formulir 'columnNum' diubah. Namun form tidak dibangun kembali dengan jumlah kolom baru meskipun $ form_state-> setRebuild (); disebut. Apakah ada cara untuk mendapatkan formulir untuk membangun kembali setelah panggilan ajax?

CATATAN: Saya sudah mencoba teknik seperti mengganti atau menambahkan item formulir di dalam panggilan ajax yang sebenarnya, tetapi ketika itu terjadi, tidak ada input ke dalam bidang yang diganti diteruskan ke $ form_state.

UPDATE: Setelah mencoba solusi 4k4, saya menerima kesalahan

Recoverable fatal error: Argument 1 passed to Drupal\Core\Render\MainContent\AjaxRenderer::renderResponse() must be of the type array, null given, called in /Library/WebServer/Documents/aaep/web/core/lib/Drupal/Core/Form/FormAjaxResponseBuilder.php on line 89 and defined in Drupal\Core\Render\MainContent\AjaxRenderer->renderResponse() (line 45 of /Library/WebServer/Documents/aaep/web/core/lib/Drupal/Core/Render/MainContent/AjaxRenderer.php).

Kepercayaannya adalah bahwa kesalahan terjadi karena $ form ['kolom'] mengembalikan nol meskipun telah dibuat sebagai wadah dalam fungsi blockForm. Saya sudah mencoba menelepon panggilan balik dengan cara lain seperti

'#ajax' => [
    'callback' => '::columnCallback',
]

dan

'#ajax' => [
    'callback' => [$this, '\Drupal\my_examples\Plugin\Block\AJAXexample::columnCallback'],
]

Tapi saya menerima kesalahan yang sama. Anehnya, ketika saya mengubah panggilan balik untuk mengembalikan seluruh formulir $ bukan hanya $ formulir ['kolom'] itu mengulangi formulir (salinan formulir muncul di bawah formulir saat ini) dan masih tanpa jumlah kolom yang tepat.


Mungkin salah ketik tapi periksa dua kali, apakah Anda tahu bahwa di kolomCallback, argumen pertama adalah salah ketik (tidak ada spasi antara array dan & $ form)?
Kevin

Jawaban:


4

Masalah pertama adalah menangani nilai untuk nomor kolom. Pada build pertama, dapatkan dari konfigurasi, membangun kembali, dapatkan dari input pengguna dan masukkan $columnNum.

Yang kedua adalah memutuskan, bagian mana dari perubahan bentuk di AJAX dan menempatkan ini dalam wadah div dengan id columns-wrapper.

class AJAXexample extends BlockBase {
    public function blockForm($form, FormStateInterface $form_state) {
        $columnNum = empty($form_state->getValue('columnNum')) ? $this->configuration['columnNum'] : $form_state->getValue('columnNum');
        $form['columnNum'] = [
            '#title'   => t('Number of Columns'),
            '#type'    => 'select',
            '#options' => [
                1         => '1',
                2         => '2',
                3         => '3',
                4         => '4',
            ],
            '#default_value' => $this->configuration['columnNum'],
            '#empty_option'  => t('-select-'),
            '#ajax'          => [
                'callback'      => [$this, 'columnCallback'],
                'wrapper'       => 'columns-wrapper', 
            ],
        ];
        $form['column'] = [
            '#type' => 'container',
            '#attributes' => ['id' => 'columns-wrapper'],
        ];
        for ($i = 0; $i < $columnNum; $i += 1) {
            $form['column'][$i] = [
                $i => [
                    '#type'       => 'details',
                    '#title'      => t('Column '.$numTitle),
                    '#open'       => FALSE,
                    'columnTitle' => [
                        '#type'      => 'textfield',
                        '#title'     => t('Column Title'),
                        '#value'     => $config[0]['columnTitle'],
                    ],  
                ],
            ];  
        return $form;
    }

Dalam panggilan balik, kita hanya perlu mengembalikan pembungkus ajax.

public function columnCallback(array&$form, FormStateInterface $form_state) {
    return $form['column'];
}

Drupal membangun kembali formulir pada setiap permintaan ajax dan memasukkannya ke dalam parameter $formpanggilan balik. Tidak masuk akal untuk mencoba membangunnya kembali.


1
Saya menerima kesalahan setelah permintaan ajax dipanggil. 'Kode Hasil HTTP: 200' StatusText: OK ResponseText:
Matt

1
Hal-hal pengujian yang saya lakukan mati (print_r ($ form_state-> getValues ​​())); dan itu benar menampilkan nilai kolomNum yang tepat. Hanya kesalahan keluar sebaliknya.
Matt

1
Saya telah memasukkan perubahan dalam kode Anda untuk demonstrasi. Tidak dapat membantu dengan debugging tanpa pesan kesalahan dengan nomor baris.
4k4

2
Apakah Anda menghapus kesalahan sintaksis dari komentar @ Kevin? Apakah ada kesalahan php di log kesalahan? Seharusnya ada banyak ketika menguji kode baru seperti ini.
4k4

2
Dilacak kesalahannya, itu berarti return $form['column']nol, karena nilai baliknya tidak dicentang renderResponse(). Mungkin masih ada masalah dengan daftar parameter callback, karena kami menempatkan setidaknya satu kontainer di kunci formulir itu dan ini akan mencegah kesalahan ini.
4k4

2

Saya kira Anda kehilangan wrappermetode di '#ajax'(sebelah callback) Anda yang terdiri dari idatribut HTML area tempat konten yang dikembalikan oleh panggilan balik harus ditempatkan. Lihat: Ajax API . Maka Anda harus memastikan wadah tersebut idada.

Contoh kode (disederhanakan):

public function blockForm($form, FormStateInterface $form_state) {
    $form['wrapper'] = array(
        '#type' => 'container',
        '#attributes' => array('id' => 'data-wrapper'),
        );
    $form['wrapper']['columnNum'] = [
        '#title'   => t('Number of Columns'),
        '#type'    => 'select',
        '#options' => [1 => '1', 2 => '2'],
        '#default_value' => $this->configuration['columnNum'],
        '#ajax'          => [
            'callback'   => '::columnCallback',
            'wrapper'    => 'data-wrapper',
        ],
    ];
}
public function columnCallback(array &$form, FormStateInterface $form_state) {
    return $form['wrapper'];
}

Untuk contoh kode lengkap, lihat: Cara Menambahkan lebih banyak opsi untuk radio jenis menggunakan Ajax di Drupal 8 .

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.