For the Optimizely module, the set of code at this point implements three different tabs, each of which contains a form. Because the code would be a bit lengthy to show in its entirety in this posting, I only provide extracts to illustrate the main points.
First, an extract from the optimizely.routing.yml file.
optimizely.acct_info:The change from the previous version of the routing file is that instead of _content the _form property is used. The value of the _form property is the namespaced path to a class that implements FormInterface. In this case the name of the class is AccountInfoForm. More about the class hierarchy below.
path: /admin/config/system/optimizely/settings
defaults:
_form: \Drupal\optimizely\AccountInfoForm
_title: Optimizely
requirements:
_permission: administer optimizely
Second, class AccountInfoForm is defined in its own file.
modules/custom/optimizely/src/AccountInfoForm.php
Here's an extract from that class definition. To keep it short and to the point, I've omitted parts of the bodies of the methods as well as boilerplate comments.
namespace Drupal\optimizely;Notes.
use Drupal\Core\Form\FormBase;
class AccountInfoForm extends FormBase {
public function getFormID() {
return 'optimizely_account_info';
}
public function buildForm(array $form,
array &$form_state) {
$form['optimizely_id'] = array(
'#type' => 'textfield',
'#title' => t('Optimizely ID Number'),
'#size' => 60,
'#maxlength' => 256,
'#required' => TRUE,
);
$form['actions'] = array('#type' => 'actions', );
$form['actions']['submit'] = array(
'#type' => 'submit',
'#value' => 'Submit',
);
return $form;
}
public function validateForm(array &$form,
array &$form_state) {
if (!preg_match('/^\d+$/',
$form_state['values']['optimizely_id'])) {
\Drupal::formBuilder()->setErrorByName(
'optimizely_id', $form_state,
t('Your Optimizely ID should be numeric.'));
}
}
public function submitForm(array &$form,
array &$form_state) {
// Code to update the database ...
// . . . . .
drupal_set_message(t('The default project ...'),
'status');
// Redirect back to projects listing.
$form_state['redirect_route']['route_name']
= 'optimizely.listing';
return;
}
}
- Class AccountInfoForm is derived from abstract class FormBase, which implements FormInterface. Because of this hierarchy, class AccountInfoForm must implement methods getFormID, buildForm, and submitForm. Implementing method validateForm is optional since FormBase contains an implementation (but it is empty, so by default no validating is done).
- Whereas in D7 the logic to build a form, validate it, and submit it are provided in three different functions that are related to each other through a naming convention, in D8 the logic is coded into three methods that are part of the same class. The class that you create implements FormInterface which declares the names and signatures of those methods. By designating the _form property in the routing file, at runtime D8 core provides for instantiating an instance of your class and for calling the methods at the appropriate times.
- In buildForm() the render arrays are largely the same as in D7 (from my limited understanding).
- To set an error message during validation, instead of calling form_set_error() call \Drupal::formBuilder()->setErrorByName() using the same parameters. Function form_set_error() is deprecated and expected to be removed.
Update for Drupal 8, beta 1: As of beta 1, there have been several API changes that affect the code here and render it partly obsolete. I have written a fresh blog post with code that is correct as of this writing. However, almost all of the notes and non-code content of this post are still accurate and useful. See http://optimizely-to-drupal-8.blogspot.com/2014/11/implementing-form-d8-beta-1.html
Sources:
Drupal 8: Forms, OOP style, August 12, 2013
http://effulgentsia.drupalgardens.com/content/drupal-8-forms-oop-style
Tutorial on writing forms in Drupal 8 modules. Author has kept code up-to-date with ongoing changes to D8. Very helpful example.
Form API in Drupal 8
https://drupal.org/node/2117411
This is a great reference with examples and explanations.
Form API Reference
https://api.drupal.org/api/drupal/developer!topics!forms_api_reference.html/7
This is from Drupal 7 but seems almost entirely applicable to D8.
interface FormInterface
https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Form!FormInterface.php/interface/FormInterface/8
function form_set_error
https://api.drupal.org/api/drupal/core!includes!form.inc/function/form_set_error/8
This function is deprecated and should not be use for new code.
No comments:
Post a Comment