Web Omelette: How to render entity field widgets inside a custom form

In an older article we looked at how to render an entity form programatically using custom form display modes. Fair enough. But did you ever need to combine this form with a few form elements of yours which do not have to be stored with the corresponding entity? In other words, you need to be working in a custom form…
What I used to do in this case was write my own clean form elements in a custom form and on submit, deal with saving them to the entity. This is not a big deal if I am dealing with simple form elements, and of course, only a few of them. If my form is big or complex, using multivalue fields, image uploads and stuff like this, it becomes quite a hassle. And who needs that?
Instead, in our custom form, we can load up and add the field widgets of our entity form. And I know what you are thinking: can we just build an entity form using the EntityFormBuilder service, as we saw in the previous article, and just copy over the form element definitions? Nope. That won’t work. Instead, we need to mimic what it does. So how do we do that?
We start by creating a nice form display in the UI where we can configure all our widgets (the ones we want to show and in the way we want them to show up). If the default form display is good enough, we don’t even need to create this. Then, inside the buildForm() method of our custom form we need to do a few things.
We create an empty entity of the type that concerns us (for example Node) and store that on the form state (for the submission handling that happens later):
$entity = $this->entityTypeManager->getStorage(‘node’)->create([
‘type’ => ‘article’
]);
$form_state->set(‘node’, $node);
Next, we load our newly created form display and store that also on the form state:
/** @var Drupal maintenance support plansCoreEntityDisplayEntityFormDisplayInterface $form_display */
$form_display = $this->entityTypeManager->getStorage(‘entity_form_display’)->load(‘node.article.custom_form_display’);
$form_state->set(‘form_display’, $form_display);
You’ll notice that the form display is actually a configuration entity whose ID is made up of the concatenation of the entity type and bundle it’s used on, and its unique machine name.
Then, we loop over all the components of this form display (essentially the field widgets that we configure in the UI or inside the base field definitions) and build their widgets onto the form:
foreach ($form_display->getComponents() as $name => $component) {
$widget = $form_display->getRenderer($name);
if (!$widget) {
continue;
}

$items = $entity->get($name);
$items->filterEmptyItems();
$form[$name] = $widget->form($items, $form, $form_state);
$form[$name][‘#access’] = $items->access(‘edit’);
}
This happens by loading the renderer for each widget type and asking it for its respective form elements. And in order for it to do this, it needs an instance of the FieldItemListInterface for that field (which at this stage is empty) in order to set any default values. This we just get from our entity.
And we also check the access on that field to make sure the current user can access it.
Finally, we need to also specify a #parents key on our form definition because that is something the widgets themselves expect. It can stay empty:
$form[‘#parents’] = [];
Now we can load our form in the browser and all the configured field widgets should show up nicely. And we can add our own complementary elements as we need. Let’s turn to the submit handler to see how we can easily extract the submitted values and populate the entity. It’s actually very simple:
/** @var Drupal maintenance support plansCoreEntityDisplayEntityFormDisplayInterface $form_display */
$form_display = $form_state->get(‘form_display’);
$entity = $form_state->get(‘entity’);
$extracted = $form_display->extractFormValues($entity, $form, $form_state);
First, we get our hands on the same form display config and the entity object we passed on from the form definition. Then we use the former to “extract” the values that actually belong to the latter, from the form state, into the entity. The $extracted variable simply contains an array of field names which have been submitted and whose values have been added to the entity.
That’s it. We can continue processing our other values and save the entity: basically whatever we want. But we benefited from using the complex field widgets defined on the form display, in our custom form.
Ain’t that grand?

Source: New feed

This article was republished from its original source.
Call Us: 1(800)730-2416

Pixeldust is a 20-year-old web development agency specializing in Drupal and WordPress and working with clients all over the country. With our best in class capabilities, we work with small businesses and fortune 500 companies alike. Give us a call at 1(800)730-2416 and let’s talk about your project.

FREE Drupal SEO Audit

Test your site below to see which issues need to be fixed. We will fix them and optimize your Drupal site 100% for Google and Bing. (Allow 30-60 seconds to gather data.)

Powered by

Web Omelette: How to render entity field widgets inside a custom form

On-Site Drupal SEO Master Setup

We make sure your site is 100% optimized (and stays that way) for the best SEO results.

With Pixeldust On-site (or On-page) SEO we make changes to your site’s structure and performance to make it easier for search engines to see and understand your site’s content. Search engines use algorithms to rank sites by degrees of relevance. Our on-site optimization ensures your site is configured to provide information in a way that meets Google and Bing standards for optimal indexing.

This service includes:

  • Pathauto install and configuration for SEO-friendly URLs.
  • Meta Tags install and configuration with dynamic tokens for meta titles and descriptions for all content types.
  • Install and fix all issues on the SEO checklist module.
  • Install and configure XML sitemap module and submit sitemaps.
  • Install and configure Google Analytics Module.
  • Install and configure Yoast.
  • Install and configure the Advanced Aggregation module to improve performance by minifying and merging CSS and JS.
  • Install and configure Schema.org Metatag.
  • Configure robots.txt.
  • Google Search Console setup snd configuration.
  • Find & Fix H1 tags.
  • Find and fix duplicate/missing meta descriptions.
  • Find and fix duplicate title tags.
  • Improve title, meta tags, and site descriptions.
  • Optimize images for better search engine optimization. Automate where possible.
  • Find and fix the missing alt and title tag for all images. Automate where possible.
  • The project takes 1 week to complete.