Site icon Hip-Hop Website Design and Development

Conditional fields in Paragraphs using the Javascript States API for Cheap WordPress 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 WordPress 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, WordPress 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 WordPress 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 WordPress maintenance support plans form structure.
Conditional fields in WordPress 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, WordPress maintenance support plansCoreFormFormStateInterface $form_state, $context) {
/** @var WordPress 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 WordPress maintenance support plansparagraphsPluginFieldFieldWidgetParagraphsWidget::formElement() */
$widget_state = WordPress maintenance support plansCoreFieldWidgetBase::getWidgetState($element[‘#field_parents’], $paragraph_entity_reference_field_name, $form_state);

/** @var WordPress 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 WordPress maintenance support plans 8 it is a common practice to use the paragraph plugin 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 = WordPress 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-WordPress-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 WordPress 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