Customizing Inline Entity Form's Complex Widget

Developer Desk

Inline Entity Form is a popular Drupal module that lets you create multiple types of content (or other related entities) from a single form. We originally created the module for Drupal 7 to improve the store administrator experience in our popular Commerce Kickstart distribution. We made it a core dependency for Commerce 2.x on Drupal 8, and today it is primarily used to let you manage order items from the order add / edit form.

I subscribe to the commerce tag on Drupal Answers to give fast advice to folks when I can, and every now and then a question intrigues me enough that I can't help but research it fully and share the results. Last week, that happened when someone asked how to add a new column to the table of order items shown on the order edit form. Since it's a table, they expected to be able to edit a View to make it work, but Inline Entity Form's "complex widget" used there is far too complex (hey, it's in the name! ; ) for Views to be of use.

The default order items table on an order edit form.
The default order items table on an order edit form.

The field widget defined by the Inline Entity Form module can be added to any Entity Reference field, itself another powerful module born out of Drupal Commerce. On the edit form, it lists all of the entities referenced by the field in a table, and operations buttons in each row let you edit or remove the referenced entities. The columns in this table are defined by an inline form handler for the referenced entity type. Inline Entity Form defines a generic handler, but modules can provide custom handlers for their entity types, as Commerce Order does for the order item entity type.

Three step solution

One of the features of this handler is a function, getTableFields(), that defines the columns of this table. Therefore, to add a SKU column, you need to take the following steps in a custom module:

  1. Alter the entity type definition for order items to supply your own inline form handler. It should extend the OrderItemInlineForm class provided by the Commerce Order module.
  2. Override the getTableFields() function, first collecting the fields defined by the parent class, adding a "callback" field for the SKU column, and repositioning the default columns so SKU goes where you want.
  3. Define the callback used to determine whether or not a given order item has a SKU (not all order items reference products) and returning it (or a placeholder value if it doesn't have one).

The customized order items table with SKUs.
The customized order items table with SKUs.

Rather than put the code for each step in a single blog post, I've published an example module with it all to GitHub in my rszrama/commerce_example1 repository. I'll just include here the code I wrote to define the SKU column:

public function getTableFields($bundles) {
  $fields = parent::getTableFields($bundles);

  $fields['sku'] = [
    'type' => 'callback',
    'callback' => 'Drupal\commerce_example1\Form\CommerceExample1OrderItemInlineForm::getOrderItemSku',
    'label' => t('SKU'),
    'weight' => 2,
  ];

  $fields['unit_price']['weight'] = 3;
  $fields['quantity']['weight'] = 4;

  return $fields;
}

You have multiple options for the type of field you can add to the table. The callback field type expects you to define a callable that Inline Entity Form will invoke to fetch the value that should be shown in your new column. You can see from my example that I chose to make this a function on my inline form handler class. To learn more about the field definitions in this array structure, refer to the documentation in InlineFormInterface.php.

Sustainable Drupal Commerce support

The Drupal Answers forum is a great place to get community support for Drupal Commerce questions. As I mentioned before, I and others on the team keep an eye out for anything we can answer quickly, but our time is limited and only rarely can we provide answers like these. Still, we do our best and often regret we can't do more.

In our ongoing pursuit to make developing the Commerce modules sustainable for the long haul, we launched Centarro Support last year to provide guaranteed Q&A to subcribers (starting at $99 / month). We deliver support there through a private Stack Overflow team, making it very familiar interface and environment, and we ensure every member of our team dedicates time each week to pick and reply to questions as soon as possible.

Add new comment