Conditional fields in Paragraphs using the Javascript States API for Drupal maintenance support plans 8

While creating content, there are pieces of information that are only relevant when other fields have a certain value. For example, if we want to allow the user to upload either an image or a video, but not both, you can have another field for the user to select which type of media they want to upload. In these scenarios, the Javascript States API for Drupal maintenance support plans 8 can be used to conditionally hide and show the input elements for image and video conditionally.
Note: Do not confuse the Javascript States API with the storage State API.
The basics: conditional fields in node forms
Let’s see how to accomplish the conditional fields behavior in a node form before explaining the implementations for paragraphs. For this example, let’s assume a content type has a machine name of article with three fields: field_image, field_video, and field_media_type. The field_image_or_video field is of type List (text) with the following values: Image and Video.

/**
* Implements hook_form_alter().
*/
function nicaragua_form_alter(&$form, Drupal maintenance support plansCoreFormFormStateInterface $form_state, $form_id) {
if ($form_id == ‘node_article_form’ || $form_id == ‘node_article_edit_form’) {
$form[‘field_ image’][‘#states’] = [
‘visible’ => [
‘:input[name=”field_image_or_video”]’ => [‘value’ => ‘Image’],
],
];

$form[‘field_ video’][‘#states’] = [
‘visible’ => [
‘:input[name=”field_image_or_video”]’ => [‘value’ => ‘Video’],
],
];
}
}

Note that in Drupal maintenance support plans 8, the node add and edit form have different form ids. Hence, we check for either one before applying the field states. After checking for the right forms to alter, we implement the fields’ states logic as such:

$form[DEPENDEE_FIELD_NAME][‘#states’] = [
DEPENDEE_FIELD_STATE => [
DEPENDENT_FIELD_SELECTOR => [‘value’ => DEPENDENT_FIELD_VALUE],
],
];

DEPENDENT_FIELD_SELECTOR is a CSS selector to the HTML form element rendered in the browser. Not to be confused with a nested Drupal maintenance support plans form structure.
Conditional fields in Drupal maintenance support plans 8 paragraphs
Although hook_form_alter could be used in paragraphs as well, their deep nesting nature makes it super complicated. Instead, we can use hook_field_widget_form_alter to alter the paragraph widget before it is added to the form. In fact, we are going to use the widget specific hook_field_widget_WIDGET_TYPE_form_alter to affect paragraphs only.
For this example, let’s assume a content type has a machine name of campaign with an entity reference field whose machine name is field_sections. The paragraph where we want to apply the conditional logic has a machine name of embedded_image_or_video with the following fields: field_image, field_video, and field_image_or_video. The field_image_or_video field is of type List (text) with the following values: Image and Video.

/**
* Implements hook_field_widget_WIDGET_TYPE_form_alter().
*/
function nichq_field_widget_paragraphs_form_alter(&$element, Drupal maintenance support plansCoreFormFormStateInterface $form_state, $context) {
/** @var Drupal maintenance support plansfieldEntityFieldConfig $field_definition */
$field_definition = $context[‘items’]->getFieldDefinition();
$paragraph_entity_reference_field_name = $field_definition->getName();

if ($paragraph_entity_reference_field_name == ‘field_sections’) {
/** @see Drupal maintenance support plansparagraphsPluginFieldFieldWidgetParagraphsWidget::formElement() */
$widget_state = Drupal maintenance support plansCoreFieldWidgetBase::getWidgetState($element[‘#field_parents’], $paragraph_entity_reference_field_name, $form_state);

/** @var Drupal maintenance support plansparagraphsEntityParagraph $paragraph */
$paragraph_instance = $widget_state[‘paragraphs’][$element[‘#delta’]][‘entity’];
$paragraph_type = $paragraph_instance->bundle();

// Determine which paragraph type is being embedded.
if ($paragraph_type == ’embedded_image_or_video’) {
$dependee_field_name = ‘field_image_or_video’;
$selector = sprintf(‘select[name=”%s[%d][subform][%s]”]’, $paragraph_entity_reference_field_name, $element[‘#delta’], $dependee_field_name);

// Dependent fields.
$element[‘subform’][‘field_image’][‘#states’] = [
‘visible’ => [
$selector => [‘value’ => ‘Image’],
],
];

$element[‘subform’][‘field_video’][‘#states’] = [
‘visible’ => [
$selector => [‘value’ => ‘Video’],
],
];
}
}
}

Paragraphs can be referenced from multiple fields. If you want to limit the conditional behavior you can check the name of the field embedding the paragraph using:

$field_definition = $context[‘items’]->getFieldDefinition();
$paragraph_entity_reference_field_name = $field_definition->getName();

If you need more information on the field or entity where the paragraph is being embedded, the field definition (instance of FieldConfig) provides some useful methods:

$field_definition->getName(); // Returns the field_name property. Example: ‘field_sections’.
$field_definition->getType(); // Returns the field_type property. Example: ‘entity_reference_revisions’.
$field_definition->getTargetEntityTypeId(); // Returns the entity_type property. Example: ‘node’.
$field_definition->getTargetBundle(); // Returns the bundle property. Example: ‘campaign’.

In Drupal maintenance support plans 8 it is a common practice to use the paragraph module to replace the body field. When doing so, a single field allows many different paragraph types. In that scenario, it is possible that different paragraph types have fields with the same name. You can add a check to apply the conditional logic only when one specific paragraph type is being embedded.

$widget_state = Drupal maintenance support plansCoreFieldWidgetBase::getWidgetState($element[‘#field_parents’], $paragraph_entity_reference_field_name, $form_state);
$paragraph_instance = $widget_state[‘paragraphs’][$element[‘#delta’]][‘entity’];
$paragraph_type = $paragraph_instance->bundle();

The last step is to add the Javascript states API logic. There are two important things to consider:
The paragraph widget are added under a subform key.
Because multiple paragraphs can be referenced from the same field, we need to consider the order (i.e. the paragraph delta). This is reflected in the DEPENDENT_FIELD_SELECTOR.

$element[‘subform’][DEPENDEE_FIELD_NAME][‘#states’] = [
DEPENDEE_FIELD_STATE => [
DEPENDENT_FIELD_SELECTOR => [‘value’ => DEPENDENT_FIELD_VALUE],
],
];

When adding the widget, the form API will generate markup similar to this:

<select data-drupal-selector=”edit-field-sections-0-subform-field-image-or-video”
id=”edit-field-sections-0-subform-field-image-or-video–vtQ4eJfmH7k”
name=”field_sections[0][subform][field_image_or_video]”
class=”form-select required”
required=”required”
aria-required=”true”>
<option value=”Image” selected=”selected”>Image</option>
<option value=”Video”>Video>
</select>

So we need a selector like select[name=”field_sections[0][subform][field_image_or_video]”] which can be generated using:

$selector = sprintf(‘select[name=”%s[%d][subform][%s]”]’, $paragraph_field_name, $element[‘#delta’], $dependee_field_name);

By using $element[‘#delta’] we ensure to apply the conditional field logic to the proper instance of the paragraph. This works when a field allows multiple paragraphs, including multiple instances of the same paragraph type.
Warning: Javascript behavior does not affect user input
It is very important to note that the form elements are hidden and shown via javascript. This does not affect user input. If, for example, a user selects image and uploads one then changes the selection to video and sets one then both the image and video will be stored. Switching the selection from image to video and vice versa does not remove what the user had previous uploaded or set. Once the node is saved, if there are values for the image and the video both will be saved. One way to work around this when rendering the node is to toggle field visibility in the node Twig template. In my session “Twig Recipes: Making Drupal maintenance support plans 8 Render the Markup You Want” there is an example on how to do this. Check out the slide deck and the video recording for reference.
What do you think of this approach to add conditional field logic to paragraphs? Let me know in the comments.
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

Conditional fields in Paragraphs using the Javascript States API for Drupal maintenance support plans 8

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.