Normalde, form değerlerini cTools nesne önbelleğini ( Drupal 7'deki Çok Adımlı formlara benzer ) kullanarak veya $form_state
(bu öğreticiye göre ) aracılığıyla adımlar arasında depolayabilirsiniz .
Drupal 8'de FormBase
yeni bir çok aşamalı sınıf oluşturmak için sınıfı devralabilirsiniz .
Drupal 8'de Çok Adımlı Formlar Oluşturma makalesinde , Drupal 8'de çok adımlı bir form oluşturmanın basit bir yolunu bulabilirsiniz.
Her şeyden önce, gerekli bağımlılıkları enjekte etmekten sorumlu temel sınıfı oluşturmanız gerekir.
Tüm form sınıflarını birlikte gruplandıracağız ve bunları demo modülümüzün plugin dizininde Multistep
bulunan yeni bir klasörün içine Form
yerleştireceğiz. Bu tamamen temiz bir yapıya sahip olmak ve hangi formların çok aşamalı form sürecimizin bir parçası olduğunu hızlı bir şekilde anlayabilmek içindir.
İşte demo kodu ( MultistepFormBase.php
dosya için):
/**
* @file
* Contains \Drupal\demo\Form\Multistep\MultistepFormBase.
*/
namespace Drupal\demo\Form\Multistep;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Session\SessionManagerInterface;
use Drupal\user\PrivateTempStoreFactory;
use Symfony\Component\DependencyInjection\ContainerInterface;
abstract class MultistepFormBase extends FormBase {
/**
* @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
*/
public function __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}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('user.private_tempstore'),
$container->get('session_manager'),
$container->get('current_user')
);
}
/**
* {@inheritdoc}.
*/
public function 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.
*/
protected function 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.
*/
protected function deleteStore() {
$keys = ['name', 'email', 'age', 'location'];
foreach ($keys as $key) {
$this->store->delete($key);
}
}
}
Ardından asıl form sınıfını şu adlı bir dosyada oluşturabilirsiniz MultistepOneForm.php
:
/**
* @file
* Contains \Drupal\demo\Form\Multistep\MultistepOneForm.
*/
namespace Drupal\demo\Form\Multistep;
use Drupal\Core\Form\FormStateInterface;
class MultistepOneForm extends MultistepFormBase {
/**
* {@inheritdoc}.
*/
public function getFormId() {
return 'multistep_form_one';
}
/**
* {@inheritdoc}.
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$form = parent::buildForm($form, $form_state);
$form['name'] = array(
'#type' => 'textfield',
'#title' => $this->t('Your name'),
'#default_value' => $this->store->get('name') ? $this->store->get('name') : '',
);
$form['email'] = array(
'#type' => 'email',
'#title' => $this->t('Your email address'),
'#default_value' => $this->store->get('email') ? $this->store->get('email') : '',
);
$form['actions']['submit']['#value'] = $this->t('Next');
return $form;
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$this->store->set('email', $form_state->getValue('email'));
$this->store->set('name', $form_state->getValue('name'));
$form_state->setRedirect('demo.multistep_two');
}
}
In buildForm()
yöntemine bizim iki kukla formu elemanlarını tanımlayan. Önce varolan form tanımını üst sınıftan aldığımızı unutmayın. Bu alanların varsayılan değerleri, bu anahtarlar için mağazada bulunan değerler olarak ayarlanır (böylece kullanıcılar geri döndüklerinde bu adımda doldurdukları değerleri görebilirler). Son olarak, eylem düğmesinin değerini İleri olarak değiştiriyoruz (bu formun son olmadığını belirtmek için).
Gelen submitForm()
yöntem mağazaya ibraz değerleri kaydetmek ve sonra, (yol bulunabilir ikinci biçimine yönlendirme demo.multistep_two
). Kodu açık tutmak için burada herhangi bir doğrulama yapmadığımızı unutmayın. Ancak çoğu kullanım durumu bazı giriş doğrulamalarını gerektirir.
Ve demo modülündeki yönlendirme dosyanızı güncelleyin ( demo.routing.yml
):
demo.multistep_one:
path: '/demo/multistep-one'
defaults:
_form: '\Drupal\demo\Form\Multistep\MultistepOneForm'
_title: 'First form'
requirements:
_permission: 'access content'
demo.multistep_two:
path: '/demo/multistep-two'
defaults:
_form: '\Drupal\demo\Form\Multistep\MultistepTwoForm'
_title: 'Second form'
requirements:
_permission: 'access content'
Son olarak, ikinci formu ( MultistepTwoForm
) oluşturun:
/**
* @file
* Contains \Drupal\demo\Form\Multistep\MultistepTwoForm.
*/
namespace Drupal\demo\Form\Multistep;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
class MultistepTwoForm extends MultistepFormBase {
/**
* {@inheritdoc}.
*/
public function getFormId() {
return 'multistep_form_two';
}
/**
* {@inheritdoc}.
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$form = parent::buildForm($form, $form_state);
$form['age'] = array(
'#type' => 'textfield',
'#title' => $this->t('Your age'),
'#default_value' => $this->store->get('age') ? $this->store->get('age') : '',
);
$form['location'] = array(
'#type' => 'textfield',
'#title' => $this->t('Your location'),
'#default_value' => $this->store->get('location') ? $this->store->get('location') : '',
);
$form['actions']['previous'] = array(
'#type' => 'link',
'#title' => $this->t('Previous'),
'#attributes' => array(
'class' => array('button'),
),
'#weight' => 0,
'#url' => Url::fromRoute('demo.multistep_one'),
);
return $form;
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$this->store->set('age', $form_state->getValue('age'));
$this->store->set('location', $form_state->getValue('location'));
// Save the data
parent::saveData();
$form_state->setRedirect('some_route');
}
}
submitForm()
Yöntemin içinde değerleri tekrar depoya kaydeder ve bu verileri uygun gördüğü şekilde devam ettirmek için üst sınıfa erteleriz. Daha sonra istediğimiz sayfaya yönlendiririz (burada kullandığımız rota kukladır).
Şimdi, PrivateTempStore
verileri birden çok istekte kullanılabilir tutmak için çalışan çok aşamalı bir formumuz olmalıdır . Daha fazla adıma ihtiyacımız varsa, tek yapmamız gereken birkaç form daha oluşturmak, bunları mevcut formların arasına eklemek ve birkaç ayar yapmaktır.