VerticalTabs.php 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. <?php
  2. namespace Drupal\Core\Render\Element;
  3. use Drupal\Core\Form\FormStateInterface;
  4. use Drupal\Core\Render\Element;
  5. /**
  6. * Provides a render element for vertical tabs in a form.
  7. *
  8. * Formats all child and non-child details elements whose #group is assigned
  9. * this element's name as vertical tabs.
  10. *
  11. * Properties:
  12. * - #default_tab: The HTML ID of the rendered details element to be used as
  13. * the default tab. View the source of the rendered page to determine the ID.
  14. *
  15. * Usage example:
  16. * @code
  17. * $form['information'] = array(
  18. * '#type' => 'vertical_tabs',
  19. * '#default_tab' => 'edit-publication',
  20. * );
  21. *
  22. * $form['author'] = array(
  23. * '#type' => 'details',
  24. * '#title' => $this->t('Author'),
  25. * '#group' => 'information',
  26. * );
  27. *
  28. * $form['author']['name'] = array(
  29. * '#type' => 'textfield',
  30. * '#title' => $this->t('Name'),
  31. * );
  32. *
  33. * $form['publication'] = array(
  34. * '#type' => 'details',
  35. * '#title' => $this->t('Publication'),
  36. * '#group' => 'information',
  37. * );
  38. *
  39. * $form['publication']['publisher'] = array(
  40. * '#type' => 'textfield',
  41. * '#title' => $this->t('Publisher'),
  42. * );
  43. * @endcode
  44. *
  45. * @FormElement("vertical_tabs")
  46. */
  47. class VerticalTabs extends RenderElement {
  48. /**
  49. * {@inheritdoc}
  50. */
  51. public function getInfo() {
  52. $class = get_class($this);
  53. return [
  54. '#default_tab' => '',
  55. '#process' => [
  56. [$class, 'processVerticalTabs'],
  57. ],
  58. '#pre_render' => [
  59. [$class, 'preRenderVerticalTabs'],
  60. ],
  61. '#theme_wrappers' => ['vertical_tabs', 'form_element'],
  62. ];
  63. }
  64. /**
  65. * Prepares a vertical_tabs element for rendering.
  66. *
  67. * @param array $element
  68. * An associative array containing the properties and children of the
  69. * vertical tabs element.
  70. *
  71. * @return array
  72. * The modified element.
  73. */
  74. public static function preRenderVerticalTabs($element) {
  75. // Do not render the vertical tabs element if it is empty.
  76. $group = implode('][', $element['#parents']);
  77. if (!Element::getVisibleChildren($element['group']['#groups'][$group])) {
  78. $element['#printed'] = TRUE;
  79. }
  80. return $element;
  81. }
  82. /**
  83. * Creates a group formatted as vertical tabs.
  84. *
  85. * @param array $element
  86. * An associative array containing the properties and children of the
  87. * details element.
  88. * @param \Drupal\Core\Form\FormStateInterface $form_state
  89. * The current state of the form.
  90. * @param array $complete_form
  91. * The complete form structure.
  92. *
  93. * @return array
  94. * The processed element.
  95. */
  96. public static function processVerticalTabs(&$element, FormStateInterface $form_state, &$complete_form) {
  97. if (isset($element['#access']) && !$element['#access']) {
  98. return $element;
  99. }
  100. // Inject a new details as child, so that form_process_details() processes
  101. // this details element like any other details.
  102. $element['group'] = [
  103. '#type' => 'details',
  104. '#theme_wrappers' => [],
  105. '#parents' => $element['#parents'],
  106. ];
  107. // Add an invisible label for accessibility.
  108. if (!isset($element['#title'])) {
  109. $element['#title'] = t('Vertical Tabs');
  110. $element['#title_display'] = 'invisible';
  111. }
  112. $element['#attached']['library'][] = 'core/drupal.vertical-tabs';
  113. // The JavaScript stores the currently selected tab in this hidden
  114. // field so that the active tab can be restored the next time the
  115. // form is rendered, e.g. on preview pages or when form validation
  116. // fails.
  117. $name = implode('__', $element['#parents']);
  118. if ($form_state->hasValue($name . '__active_tab')) {
  119. $element['#default_tab'] = $form_state->getValue($name . '__active_tab');
  120. }
  121. $element[$name . '__active_tab'] = [
  122. '#type' => 'hidden',
  123. '#default_value' => $element['#default_tab'],
  124. '#attributes' => ['class' => ['vertical-tabs__active-tab']],
  125. ];
  126. // Clean up the active tab value so it's not accidentally stored in
  127. // settings forms.
  128. $form_state->addCleanValueKey($name . '__active_tab');
  129. return $element;
  130. }
  131. }