Details.php 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. <?php
  2. namespace Drupal\Core\Render\Element;
  3. use Drupal\Core\Render\Element;
  4. /**
  5. * Provides a render element for a details element, similar to a fieldset.
  6. *
  7. * Fieldsets can only be used in forms, while details elements can be used
  8. * outside of forms. Users click on the title to open or close the details
  9. * element, showing or hiding the contained elements.
  10. *
  11. * Properties:
  12. * - #title: The title of the details container. Defaults to "Details".
  13. * - #open: Indicates whether the container should be open by default.
  14. * Defaults to FALSE.
  15. * - #summary_attributes: An array of attributes to apply to the <summary>
  16. * element.
  17. *
  18. * Usage example:
  19. * @code
  20. * $form['author'] = array(
  21. * '#type' => 'details',
  22. * '#title' => $this->t('Author'),
  23. * );
  24. *
  25. * $form['author']['name'] = array(
  26. * '#type' => 'textfield',
  27. * '#title' => $this->t('Name'),
  28. * );
  29. * @endcode
  30. *
  31. * @see \Drupal\Core\Render\Element\Fieldset
  32. * @see \Drupal]Core\Render\Element\VerticalTabs
  33. *
  34. * @RenderElement("details")
  35. */
  36. class Details extends RenderElement {
  37. /**
  38. * {@inheritdoc}
  39. */
  40. public function getInfo() {
  41. $class = get_class($this);
  42. return [
  43. '#open' => FALSE,
  44. '#summary_attributes' => [],
  45. '#value' => NULL,
  46. '#process' => [
  47. [$class, 'processGroup'],
  48. [$class, 'processAjaxForm'],
  49. ],
  50. '#pre_render' => [
  51. [$class, 'preRenderDetails'],
  52. [$class, 'preRenderGroup'],
  53. ],
  54. '#theme_wrappers' => ['details'],
  55. ];
  56. }
  57. /**
  58. * Adds form element theming to details.
  59. *
  60. * @param $element
  61. * An associative array containing the properties and children of the
  62. * details.
  63. *
  64. * @return
  65. * The modified element.
  66. */
  67. public static function preRenderDetails($element) {
  68. Element::setAttributes($element, ['id']);
  69. // The .js-form-wrapper class is required for #states to treat details like
  70. // containers.
  71. static::setAttributes($element, ['js-form-wrapper', 'form-wrapper']);
  72. // Collapsible details.
  73. $element['#attached']['library'][] = 'core/drupal.collapse';
  74. // Open the detail if specified or if a child has an error.
  75. if (!empty($element['#open']) || !empty($element['#children_errors'])) {
  76. $element['#attributes']['open'] = 'open';
  77. }
  78. // Do not render optional details elements if there are no children.
  79. if (isset($element['#parents'])) {
  80. $group = implode('][', $element['#parents']);
  81. if (!empty($element['#optional']) && !Element::getVisibleChildren($element['#groups'][$group])) {
  82. $element['#printed'] = TRUE;
  83. }
  84. }
  85. return $element;
  86. }
  87. }