Cara termudah untuk melakukan ini adalah dengan menggunakan $ form_state. Dalam metode formBuild () Anda, Anda memiliki if / else atau beralih berdasarkan sesuatu seperti $form_state['step']dan menampilkan elemen formulir yang berbeda. Kemudian Anda memiliki hal yang sama dalam mengirimkan panggilan balik atau memiliki beberapa panggilan balik pengiriman, yang melakukan sesuatu pada objek di $ form_state yang sedang Anda bangun, ubah langkahnya dan tetapkan $form_state['rebuild']bendera ke TRUE.
Ada beberapa kelemahan dari pendekatan itu, itulah sebabnya (di antara alasan lain) wisaya bentuk ctools dibuat. Ini bisa menjadi rumit jika Anda memiliki beberapa langkah dan harus mendefinisikan semua itu dalam satu fungsi bentuk / kelas dan semuanya terjadi dalam permintaan POST.
Apa yang dilakukan wizard formulir ctools adalah mengelompokkan beberapa, memisahkan formulir bersama dan mengontrol navigasi dari satu ke yang lain. Anda juga menggunakan cache objek ctools untuk menyimpan objek Anda alih-alih $ form_state, karena itu tidak lagi dibagikan di seluruh formulir Anda.
Meskipun sistem itu belum ada, cache objek ctools telah dipindahkan ke 8.x dan sekarang disebut pengguna tempstore, tersedia sebagai layanan: \Drupal::service('user.private_tempstore')(sebelum 8.0-beta8 dipanggil user.tempstore). Ini adalah lapisan di atas toko nilai kunci kedaluwarsa yang memperkenalkan kepemilikan data yang disimpan di sana. Jadi inilah yang memberdayakan pesan terkenal dalam tampilan bahwa pengguna yang berbeda saat ini mengedit tampilan itu dan dikunci karena alasan itu. Keuntungan lain daripada menggunakan $ _SESSION untuk itu adalah bahwa data Anda hanya harus dimuat saat dibutuhkan, ketika Anda mengedit 3 tampilan, kemudian menggunakan $ _SESSION akan berarti bahwa Anda harus memuat dan membawanya sekitar pada setiap permintaan satu halaman.
Jika Anda tidak membutuhkannya, maka Anda bisa mengandalkan sesi atau juga langsung meletakkannya di toko nilai kunci yang diharapkan ($ form_state disimpan di sana sekarang juga, bukan cache pseudo seperti pada 7.x).
Namun sistem konfigurasi tidak cocok. Itu tidak dimaksudkan untuk konten per pengguna (atau konten sama sekali) karena tidak benar-benar skala untuk menyimpan ribuan atau puluhan ribu catatan dan mungkin membuat beberapa asumsi untuk memuat semua yang mungkin diperlukan pada permintaan halaman tertentu ( belum, tetapi ada masalah untuk mewujudkannya)
Satu lagi pertanyaan tentang jawaban Anda. Ini mungkin pertanyaan konyol: Apakah \ Drupal :: service ('user.tempstore') juga tersedia untuk pengguna anonim?
Biasanya Anda bisa menyimpan nilai formulir di antara langkah-langkah menggunakan cache objek cTools (mirip dengan formulir Multistep di Drupal 7 ), atau melalui $form_state(sesuai tutorial ini ).
Di Drupal 8 Anda bisa mewarisi FormBasekelas untuk membuat kelas multistep baru.
Pertama-tama, Anda harus membuat kelas dasar yang akan bertugas menyuntikkan dependensi yang diperlukan.
Kami akan mengelompokkan semua kelas formulir bersama dan menempatkannya di dalam folder baru bernama Multistepterletak di dalam Formdirektori plugin modul demo kami. Ini murni untuk memiliki struktur yang bersih dan dapat dengan cepat mengetahui bentuk mana yang merupakan bagian dari proses formulir multi-langkah kami.
Berikut adalah kode demo (untuk MultistepFormBase.phpfile):
/**
* @file
* Contains \Drupal\demo\Form\Multistep\MultistepFormBase.
*/namespaceDrupal\demo\Form\Multistep;useDrupal\Core\Form\FormBase;useDrupal\Core\Form\FormStateInterface;useDrupal\Core\Session\AccountInterface;useDrupal\Core\Session\SessionManagerInterface;useDrupal\user\PrivateTempStoreFactory;useSymfony\Component\DependencyInjection\ContainerInterface;abstractclassMultistepFormBaseextendsFormBase{/**
* @var \Drupal\user\PrivateTempStoreFactory
*/protected $tempStoreFactory;/**
* @var \Drupal\Core\Session\SessionManagerInterface
*/private $sessionManager;/**
* @var \Drupal\Core\Session\AccountInterface
*/private $currentUser;/**
* @var \Drupal\user\PrivateTempStore
*/protected $store;/**
* Constructs a \Drupal\demo\Form\Multistep\MultistepFormBase.
*
* @param \Drupal\user\PrivateTempStoreFactory $temp_store_factory
* @param \Drupal\Core\Session\SessionManagerInterface $session_manager
* @param \Drupal\Core\Session\AccountInterface $current_user
*/publicfunction __construct(PrivateTempStoreFactory $temp_store_factory,SessionManagerInterface $session_manager,AccountInterface $current_user){
$this->tempStoreFactory = $temp_store_factory;
$this->sessionManager = $session_manager;
$this->currentUser = $current_user;
$this->store = $this->tempStoreFactory->get('multistep_data');}/**
* {@inheritdoc}
*/publicstaticfunction create(ContainerInterface $container){returnnewstatic(
$container->get('user.private_tempstore'),
$container->get('session_manager'),
$container->get('current_user'));}/**
* {@inheritdoc}.
*/publicfunction buildForm(array $form,FormStateInterface $form_state){// Start a manual session for anonymous users.if($this->currentUser->isAnonymous()&&!isset($_SESSION['multistep_form_holds_session'])){
$_SESSION['multistep_form_holds_session']=true;
$this->sessionManager->start();}
$form = array();
$form['actions']['#type']='actions';
$form['actions']['submit']= array('#type'=>'submit','#value'=> $this->t('Submit'),'#button_type'=>'primary','#weight'=>10,);return $form;}/**
* Saves the data from the multistep form.
*/protectedfunction saveData(){// Logic for saving data goes here...
$this->deleteStore();
drupal_set_message($this->t('The form has been saved.'));}/**
* Helper method that removes all the keys from the store collection used for
* the multistep form.
*/protectedfunction deleteStore(){
$keys =['name','email','age','location'];foreach($keys as $key){
$this->store->delete($key);}}}
Kemudian Anda bisa membuat kelas bentuk aktual di dalam file bernama MultistepOneForm.php:
Dalam buildForm()metode ini kita mendefinisikan dua elemen bentuk boneka kami. Perhatikan bahwa kami mengambil definisi formulir yang ada dari kelas induk terlebih dahulu. Nilai default untuk bidang ini ditetapkan sebagai nilai yang ditemukan di toko untuk kunci tersebut (sehingga pengguna dapat melihat nilai yang mereka isi pada langkah ini jika mereka kembali ke sana). Akhirnya, kami mengubah nilai tombol tindakan ke Berikutnya (untuk menunjukkan bahwa formulir ini bukan yang terakhir).
Dalam submitForm()metode kami menyimpan nilai yang dikirimkan ke toko dan kemudian mengarahkan ulang ke bentuk kedua (yang dapat ditemukan di rute demo.multistep_two). Ingatlah bahwa kami tidak melakukan validasi apa pun di sini untuk menjaga kode tetap ringan. Tetapi sebagian besar kasus penggunaan akan meminta beberapa validasi input.
Dan perbarui file perutean Anda di modul demo ( demo.routing.yml):
Di dalam submitForm()metode kami sekali lagi menyimpan nilai-nilai ke toko dan tunduk pada kelas induk untuk bertahan data ini dengan cara apa pun yang menurutnya cocok. Kami kemudian mengarahkan ke halaman apa pun yang kami inginkan (rute yang kami gunakan di sini adalah dummy).
Kami sekarang harus memiliki formulir multistep yang berfungsi yang menggunakan PrivateTempStoreuntuk menjaga data tersedia di beberapa permintaan. Jika kita membutuhkan lebih banyak langkah, yang harus kita lakukan adalah membuat beberapa formulir lagi, menambahkannya di antara yang sudah ada dan membuat beberapa penyesuaian.
Panduan multistep yang telah Anda sebutkan, sudah terintegrasi dengan CTools, lihat: Dukungan Wizard untuk 8.x-3.x , jadi Anda dapat mempertimbangkan untuk memperluasnya your_module.services.yml, misalnya
kemudian rentangkan kelas di src/Controller/MyWizardForm.php:
<?php/**
* @file
* Contains \Drupal\MyModuleMultistep\Controller\MyWizardForm
*/namespaceDrupal\MyModuleMultistep\Controller;/**
* Wrapping controller for wizard forms that serve as the main page body.
*/classMyWizardFormextendsWizardFormController{}
Anda tahu contoh yang bisa membantu memahami cara menggunakan wizard multistep CTools?
Duncanmoo
1
@Duncanmoo Saya tidak punya, tetapi merasa bebas untuk mengajukan pertanyaan lain dengan masalah spesifik yang Anda alami, atau mencari di Tests/Wizard/CToolsWizard*file di mana Anda dapat menemukan beberapa tes (misalnya testWizardSteps).
Biasanya Anda bisa menyimpan nilai formulir di antara langkah-langkah menggunakan cache objek cTools (mirip dengan formulir Multistep di Drupal 7 ), atau melalui
$form_state
(sesuai tutorial ini ).Di Drupal 8 Anda bisa mewarisi
FormBase
kelas untuk membuat kelas multistep baru.Dalam artikel Cara Membangun Formulir multi-langkah di Drupal 8 Anda bisa menemukan cara sederhana untuk membuat formulir multistep di Drupal 8.
Pertama-tama, Anda harus membuat kelas dasar yang akan bertugas menyuntikkan dependensi yang diperlukan.
Berikut adalah kode demo (untuk
MultistepFormBase.php
file):Kemudian Anda bisa membuat kelas bentuk aktual di dalam file bernama
MultistepOneForm.php
:Dan perbarui file perutean Anda di modul demo (
demo.routing.yml
):Akhirnya, buat formulir kedua (
MultistepTwoForm
):sumber
Panduan multistep yang telah Anda sebutkan, sudah terintegrasi dengan CTools, lihat: Dukungan Wizard untuk 8.x-3.x , jadi Anda dapat mempertimbangkan untuk memperluasnya
your_module.services.yml
, misalnyakemudian rentangkan kelas di
src/Controller/MyWizardForm.php
:sumber
Tests/Wizard/CToolsWizard*
file di mana Anda dapat menemukan beberapa tes (misalnyatestWizardSteps
).