9.8. Rad sa formularima u Drupalu. Dodavanje konfiguracionog formulara programatski.
U ovom tutorijalu bavićemo se Drupal Form API-jem i kreirati formular za podešavanja modula. Već smo napravili module za prikaz stranice i bloka, sada ćemo napraviti konfiguracioni formular u koji ćemo smestiti podatke za povezivanje sa uslovnom uslugom. Recimo da na sajtu treba da sačuvamo API ključ i API Client ID, na primer za Google Maps API.
Primere koda možete pogledati na github-u:
https://github.com/levmyshkin/drupalbook8
Ove podatke možemo čuvati u settings.php i dodati ta podešavanja u git. Ali to nije sigurno, bolje je pristup servisima čuvati u bazi podataka.
Dodajmo još jednu rutu za naš formular:
modules/custom/drupalbook/drupalbook.routing.yml
drupalbook.settings:
path: '/admin/structure/drupalbook/settings'
defaults:
_form: '\Drupal\drupalbook\Form\DrupalbookSettingsForm'
_title: 'DrupalBook Settings form'
requirements:
_permission: 'administer site configuration'
Za razliku od prethodnih ruta, ovde u defaults navodimo ne _controller, već _form. To je zato što ne pravimo Controller klasu za formular, već form klasu. Hajde da kreiramo fajl za klasu formulara:
modules/custom/drupalbook/src/Form/DrupalbookSettingsForm.php
Treba da napravite poseban folder Form u src folderu za vaše forme. To omogućava da kod modula organizujete u posebne foldere i lakše pronađete potrebni kod po imenu foldera.
Dodajte sledeći kod formulara i analiziraćemo svaki blok koda i kako radi:
<?php
namespace Drupal\drupalbook\Form;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
/**
* Konfiguriše primer podešavanja za ovaj sajt.
*/
class DrupalbookSettingsForm extends ConfigFormBase {
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'drupalbook_admin_settings';
}
/**
* {@inheritdoc}
*/
protected function getEditableConfigNames() {
return [
'drupalbook.settings',
];
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$config = $this->config('drupalbook.settings');
$form['drupalbook_api_key'] = array(
'#type' => 'textfield',
'#title' => $this->t('API Key'),
'#default_value' => $config->get('drupalbook_api_key'),
);
$form['drupalbook_api_client_id'] = array(
'#type' => 'textfield',
'#title' => $this->t('API Client ID'),
'#default_value' => $config->get('drupalbook_api_client_id'),
);
return parent::buildForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
// Uzimamo konfiguraciju
$this->configFactory->getEditable('drupalbook.settings')
// Postavljamo poslatu vrednost u konfiguraciju
->set('drupalbook_api_key', $form_state->getValue('drupalbook_api_key'))
// Možete postaviti više podešavanja odjednom sa više poziva set()
->set('drupalbook_api_client_id', $form_state->getValue('drupalbook_api_client_id'))
->save();
parent::submitForm($form, $form_state);
}
}
Već smo se bavili namespace i use naredbama, Drupal koristi automatsko povezivanje samo potrebnih klasa:
\drupalbook\Form;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
Za kreiranje konfiguracionog formulara nasleđujemo ConfigFormBase klasu, što implicira da će podaci sa forme biti sačuvani u konfiguraciji.
extends ConfigFormBase {
Zatim navodimo jedinstveni ID forme. Ako ID forme počinje imenom modula, sigurno će biti jedinstven:
function getFormId() {
return 'drupalbook_admin_settings';
}
Navodimo grupu konfiguracija u kojoj ćemo čuvati podatke:
function getEditableConfigNames() {
return [
'drupalbook.settings',
];
}
Sada pogledajmo kako pravimo sama polja forme. Mogućnosti Form API-ja i dostupna polja možete proučiti u dokumentaciji:
https://api.drupal.org/api/drupal/elements/8.5.x
Do sada smo koristili samo textfield:
Ali često se sreću i drop-down liste:
Checkbox-ovi i radio dugmad:
Probajte da dodate polja u formu, ne ograničavajte se samo na textfield.
function buildForm(array $form, FormStateInterface $form_state) {
$config = $this->config('drupalbook.settings');
Formu pravimo kao niz $form iz kog se kasnije gradi HTML. Varijabla $form_state čuva sve podatke sa forme koje šaljemo, uključujući vrednosti svih polja, form_id, CSRF token za zaštitu. $form_state omogućava i prenos podataka između koraka višestepenog formulara, što ćemo koristiti u nekoj od narednih lekcija. Takođe, svaki put kada se forma šalje preko AJAX-a, forma se ponovo gradi, i $form_state omogućava da se sačuva prethodno stanje forme pre klika na dugme za slanje. Ako dođe do greške (na primer, nije popunjeno obavezno polje), svi podaci će ostati sačuvani u poljima kroz $form_state. Zato $form i $form_state uvek idu zajedno.
Ovde takođe učitavamo podatke iz konfiguracije. Možda ste već sačuvali neke vrednosti u drupalbook.settings i $config nije prazan, pa će se trenutne vrednosti prikazati u poljima kroz #default_value, koje koristi get() metod konfiguracije.
$form['drupalbook_api_key'] = array(
'#type' => 'textfield',
'#title' => $this->t('API Key'),
'#default_value' => $config->get('drupalbook_api_key'),
);
$form['drupalbook_api_client_id'] = array(
'#type' => 'textfield',
'#title' => $this->t('API Client ID'),
'#default_value' => $config->get('drupalbook_api_client_id'),
);
Na kraju metode vraćamo $form i $form_state da bi forma bila izgrađena:
return parent::buildForm($form, $form_state);
Sledeća je metoda submitForm(), koja se poziva ako je forma uspešno poslata bez grešaka. Ako niste popunili obavezno polje i Drupal prijavi grešku, submitForm se neće pozvati. Ako želite da proverite podatke pri slanju, koristite validateForm(), koji se izvršava i ako ima grešaka, i može poništiti slanje ako podaci nisu validni. Validate ćemo obraditi u narednim lekcijama o formama.
U submitForm() uzimamo vrednosti iz polja i ažuriramo konfiguraciju drupalbook.settings:
public function submitForm(array &$form, FormStateInterface $form_state) {
$this->configFactory->getEditable('drupalbook.settings')
->set('drupalbook_api_key', $form_state->getValue('drupalbook_api_key'))
->set('drupalbook_api_client_id', $form_state->getValue('drupalbook_api_client_id'))
->save();
parent::submitForm($form, $form_state);
}
Pozivamo i roditeljsku metodu submitForm koja prikazuje poruku o uspešnom snimanju forme. Tu liniju možete komentarisati i napisati svoju poruku:
//parent::submitForm($form, $form_state);
drupal_set_message($this->t('Moj super formular je sačuvan!'));
Zapamtite da očistite keš da bi ruta proradila. Sada možete probati svoj formular u akciji. Kada vam treba API ključ, možete koristiti ovaj kod:
$config = \Drupal::config('drupalbook.settings');
$api_key = $config->get('drupalbook_api_key');
$api_client_id = $config->get('drupalbook_api_client_id');
Ovaj kod će raditi u bilo kom modulu ili funkciji za pripremu (preprocess), jer Drupal ima jedinstven sistem konfiguracije.
To je to za narednu lekciju o formama, u narednoj ćemo analizirati kako napraviti višestepene forme.
Primere koda možete pogledati na github-u:
https://github.com/levmyshkin/drupalbook8