Drupal 8 - Conditionally hide a form field

Use case

You want to visually hide/show a form field, based on a specific value from another field. Or you want to perform any of the following actions on a form field, based on a specific value from another field.

  • enable/disable
  • required/optional
  • visible/invisible
  • checked/unchecked
  • expanded/collapsed

Solution

There is a nice module called Conditional Fields which offers a lot of options for use cases like these or even more complex ones. But it's under development for Drupal 8 and not ready yet at the time of writing.

But if you only need to implement simple functionality like mentioned in the use case, you can use #states as well, which is part of the Drupal core form API.

Suppose, we have an select field field_album_type and an input field field_album_type_name respectively. And we want to show field_album_type_name whenever value of field_album_type is 'custom'.

If you are building your own form then you can set #states while building the form. Otherwise you can implement hook_form_FORM_ID_alter, to alter existing form and set #states.

use Drupal\Core\Form\FormStateInterface;

/**
 * Implements hook_form_FORM_ID_alter().
 */
function music_form_node_album_edit_form_alter(&$form, FormStateInterface &$form_state, $form_id) {
  $form['field_album_type_name']['#states'] = [
    'visible' => [
      'select[name="field_album_type"]' => ['value' => 'custom']
    ]
  ];
}

As stated in documentation, state work with condition array. Condition array consists of JQUERY_SELECTOR and REMOTE_CONDITIONS.

JQUERY_SELECTOR is one of any valid jquery selectors. In Drupal documentation examples, mostly :inputselector is being used. While it's easy to use :input selector as it works for any kind of form element, it's slow as compared to other specific selectors as stated in jQuery documentation as well. For this reason, I would suggest using specific selector whenever you can.

Multiple conditions

Array format of #states is a bit different when you need to check for multiple conditions in same field.

Suppose we want to show field_album_type_name whenever value of field_album_type is 'custom' OR 'other'.

use Drupal\Core\Form\FormStateInterface;

/**
 * Implements hook_form_FORM_ID_alter().
 */
function music_form_node_album_edit_form_alter(&$form, FormStateInterface &$form_state, $form_id) {
  $form['field_album_type_name']['#states'] = [
    'visible' => [
      ['select[name="field_album_type"]' => ['value' => 'custom']],
      'or',
      ['select[name="field_album_type"]' => ['value' => 'other']]
    ]
  ];
}

or condition is the default one and following code will do the same job as the above one:

use Drupal\Core\Form\FormStateInterface;

/**
 * Implements hook_form_FORM_ID_alter().
 */
function music_form_node_album_edit_form_alter(&$form, FormStateInterface &$form_state, $form_id) {
  $form['field_album_type_name']['#states'] = [
    'visible' => [
      ['select[name="field_album_type"]' => ['value' => 'custom']],
      ['select[name="field_album_type"]' => ['value' => 'other']]
    ]
  ];
}

Other than or, support for xor is available as well.

Reference


  PHP, Drupal 8