Creating a checkout pane in Drupal 8 Commerce


Campbell Tilley


In this article we will look at what's involved in creating a custom checkout pane. The example checkout pane will enable a customer comments section in the Order Information step.

Unlike working on forms with Webform, Commerce has no UI to build forms. Instead, we need to build a custom plugin.

Our checkout pane plugin needs to have the correct namespace and annotations set. Create a new class in MyModule/src/Plugin/Commerce/CheckoutPane directory and add the below code to start.


namespace Drupal\MyModule\Plugin\Commerce\CheckoutPane;

use Drupal\commerce_checkout\Plugin\Commerce\CheckoutPane\CheckoutPaneBase;
use Drupal\commerce_checkout\Plugin\Commerce\CheckoutPane\CheckoutPaneInterface;
use Drupal\Core\Form\FormStateInterface;

 * Allows customers to add comments to the order.
 * @CommerceCheckoutPane(
 *   id = "customer_comments",
 *   label = @Translation("Additional Information"),
 *   default_step = "order_information",
 *   wrapper_element = "fieldset",
 * )
class OrderNotes extends CheckoutPaneBase implements CheckoutPaneInterface {

Our checkout pane ID is customer_comments and the fieldset will have the title of Additional Information. Using fieldset as the wrapper element will mean our checkout pane will be more inline with the existing checkout panes in this step. You can then also extend this fieldset if you require more than customer comments.

Next we will build our form.

   * {@inheritdoc}
  public function buildPaneForm(array $pane_form, FormStateInterface $form_state, array &$complete_form) {
    $pane_form['customer_comments'] = [
      '#type' => 'textarea',
      '#title' => $this->t('Order notes'),
      '#default_value' => $this->order->get('field_customer_comments')->getString(),
      '#required' => FALSE,
    return $pane_form;

We have used a field here that has not yet been created field_customer_comments. Continue and we will add this once we have finished our class.

Now we need to configure what happens when the form is submitted.

   * {@inheritdoc}
  public function submitPaneForm(array &$pane_form, FormStateInterface $form_state, array &$complete_form) {
    $value = $form_state->getValue($pane_form['#parents']);
    $this->order->set('field_customer_comments', $value['customer_comments']);

This will save the text entered into field_customer_comments for us to view in the review pane. Which leads us to the final part of our class. We need to add our customer comments to the review pane. We can do this by using the function buildPaneSummary.

   * {@inheritdoc}
  public function buildPaneSummary() {
    return ['#markup' => $this->order->get('field_customer_comments')->getString()];

Now that our class if configured, navigate to the Manage Fields page of your Order type and add in a plain text field with the machine name field_customer_comments.

Finally, clear the cache and test out the new pane on your checkout form.

If you have any questions or would like to know how to add these comments onto your receipt, leave a comment below.


bug in last code sample

In your last code sample you refer to 'field_order_notes' while previously you were calling it 'field_customer_comments'. I'm quite sure this won't work properly and was not tested as presented.

Thanks for picking that up!…

Thanks for picking that up! I have updated that now

Add new comment

The content of this field is kept private and will not be shown publicly.

Plain text

  • No HTML tags allowed.
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.


  • Allowed HTML tags: <em> <strong> <cite> <blockquote cite> <ul type> <ol start type> <li> <dl> <dt> <dd> <p>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.
  • Use [gist:#####] where ##### is your gist number to embed the gist
    You may also include a specific file within a multi-file gist with [gist:####:my_file].

Spread the word