You are here

class Tableselect in Zircon Profile 8

Same name and namespace in other branches
  1. 8.0 core/lib/Drupal/Core/Render/Element/Tableselect.php \Drupal\Core\Render\Element\Tableselect

Provides a form element for a table with radios or checkboxes in left column.

Properties:

  • #headers: Table headers used in the table.
  • #options: An associative array where each key is the value returned when a user selects the radio button or checkbox, and each value is the row of table data.

Usage example: See https://www.drupal.org/node/945102 for an example and full explanation.

Plugin annotation

@FormElement("tableselect");

Hierarchy

Expanded class hierarchy of Tableselect

See also

\Drupal\Core\Render\Element\Table

1 file declares its use of Tableselect
TableSelectTest.php in core/tests/Drupal/Tests/Core/Render/Element/TableSelectTest.php
Contains \Drupal\Tests\Core\Render\Element\TableSelectTest.
8 #type uses of Tableselect
AddHandler::buildForm in core/modules/views_ui/src/Form/Ajax/AddHandler.php
Form constructor.
CommentAdminOverview::buildForm in core/modules/comment/src/Form/CommentAdminOverview.php
Form constructor for the comment overview administration form.
DatabaseTestForm::buildForm in core/modules/system/tests/modules/database_test/src/Form/DatabaseTestForm.php
Form constructor.
ElementsTableSelectTest::testMultipleFalseOptionchecker in core/modules/system/src/Tests/Form/ElementsTableSelectTest.php
Test the whether the option checker gives an error on invalid tableselect values for radios.
ElementsTableSelectTest::testMultipleTrueOptionchecker in core/modules/system/src/Tests/Form/ElementsTableSelectTest.php
Test the whether the option checker gives an error on invalid tableselect values for checkboxes.

... See full list

File

core/lib/Drupal/Core/Render/Element/Tableselect.php, line 31
Contains \Drupal\Core\Render\Element\Tableselect.

Namespace

Drupal\Core\Render\Element
View source
class Tableselect extends Table {

  /**
   * {@inheritdoc}
   */
  public function getInfo() {
    $class = get_class($this);
    return array(
      '#input' => TRUE,
      '#js_select' => TRUE,
      '#multiple' => TRUE,
      '#responsive' => TRUE,
      '#sticky' => FALSE,
      '#pre_render' => array(
        array(
          $class,
          'preRenderTable',
        ),
        array(
          $class,
          'preRenderTableselect',
        ),
      ),
      '#process' => array(
        array(
          $class,
          'processTableselect',
        ),
      ),
      '#options' => array(),
      '#empty' => '',
      '#theme' => 'table__tableselect',
    );
  }

  /**
   * {@inheritdoc}
   */
  public static function valueCallback(&$element, $input, FormStateInterface $form_state) {

    // If $element['#multiple'] == FALSE, then radio buttons are displayed and
    // the default value handling is used.
    if (isset($element['#multiple']) && $element['#multiple']) {

      // Checkboxes are being displayed with the default value coming from the
      // keys of the #default_value property. This differs from the checkboxes
      // element which uses the array values.
      if ($input === FALSE) {
        $value = array();
        $element += array(
          '#default_value' => array(),
        );
        foreach ($element['#default_value'] as $key => $flag) {
          if ($flag) {
            $value[$key] = $key;
          }
        }
        return $value;
      }
      else {
        return is_array($input) ? array_combine($input, $input) : array();
      }
    }
  }

  /**
   * Prepares a 'tableselect' #type element for rendering.
   *
   * Adds a column of radio buttons or checkboxes for each row of a table.
   *
   * @param array $element
   *   An associative array containing the properties and children of
   *   the tableselect element. Properties used: #header, #options, #empty,
   *   and #js_select. The #options property is an array of selection options;
   *   each array element of #options is an array of properties. These
   *   properties can include #attributes, which is added to the
   *   table row's HTML attributes; see table.html.twig. An example of per-row
   *   options:
   *   @code
   *     $options = array(
   *       array(
   *         'title' => 'How to Learn Drupal',
   *         'content_type' => 'Article',
   *         'status' => 'published',
   *         '#attributes' => array('class' => array('article-row')),
   *       ),
   *       array(
   *         'title' => 'Privacy Policy',
   *         'content_type' => 'Page',
   *         'status' => 'published',
   *         '#attributes' => array('class' => array('page-row')),
   *       ),
   *     );
   *     $header = array(
   *       'title' => t('Title'),
   *       'content_type' => t('Content type'),
   *       'status' => t('Status'),
   *     );
   *     $form['table'] = array(
   *       '#type' => 'tableselect',
   *       '#header' => $header,
   *       '#options' => $options,
   *       '#empty' => t('No content available.'),
   *     );
   *   @endcode
   *
   * @return array
   *   The processed element.
   */
  public static function preRenderTableselect($element) {
    $rows = array();
    $header = $element['#header'];
    if (!empty($element['#options'])) {

      // Generate a table row for each selectable item in #options.
      foreach (Element::children($element) as $key) {
        $row = array();
        $row['data'] = array();
        if (isset($element['#options'][$key]['#attributes'])) {
          $row += $element['#options'][$key]['#attributes'];
        }

        // Render the checkbox / radio element.
        $row['data'][] = drupal_render($element[$key]);

        // As table.html.twig only maps header and row columns by order, create
        // the correct order by iterating over the header fields.
        foreach ($element['#header'] as $fieldname => $title) {

          // A row cell can span over multiple headers, which means less row
          // cells than headers could be present.
          if (isset($element['#options'][$key][$fieldname])) {

            // A header can span over multiple cells and in this case the cells
            // are passed in an array. The order of this array determines the
            // order in which they are added.
            if (is_array($element['#options'][$key][$fieldname]) && !isset($element['#options'][$key][$fieldname]['data'])) {
              foreach ($element['#options'][$key][$fieldname] as $cell) {
                $row['data'][] = $cell;
              }
            }
            else {
              $row['data'][] = $element['#options'][$key][$fieldname];
            }
          }
        }
        $rows[] = $row;
      }

      // Add an empty header or a "Select all" checkbox to provide room for the
      // checkboxes/radios in the first table column.
      if ($element['#js_select']) {

        // Add a "Select all" checkbox.
        $element['#attached']['library'][] = 'core/drupal.tableselect';
        array_unshift($header, array(
          'class' => array(
            'select-all',
          ),
        ));
      }
      else {

        // Add an empty header when radio buttons are displayed or a "Select all"
        // checkbox is not desired.
        array_unshift($header, '');
      }
    }
    $element['#header'] = $header;
    $element['#rows'] = $rows;
    return $element;
  }

  /**
   * Creates checkbox or radio elements to populate a tableselect table.
   *
   * @param array $element
   *   An associative array containing the properties and children of the
   *   tableselect element.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   * @param array $complete_form
   *   The complete form structure.
   *
   * @return array
   *   The processed element.
   */
  public static function processTableselect(&$element, FormStateInterface $form_state, &$complete_form) {
    if ($element['#multiple']) {
      $value = is_array($element['#value']) ? $element['#value'] : array();
    }
    else {

      // Advanced selection behavior makes no sense for radios.
      $element['#js_select'] = FALSE;
    }
    $element['#tree'] = TRUE;
    if (count($element['#options']) > 0) {
      if (!isset($element['#default_value']) || $element['#default_value'] === 0) {
        $element['#default_value'] = array();
      }

      // Create a checkbox or radio for each item in #options in such a way that
      // the value of the tableselect element behaves as if it had been of type
      // checkboxes or radios.
      foreach ($element['#options'] as $key => $choice) {

        // Do not overwrite manually created children.
        if (!isset($element[$key])) {
          if ($element['#multiple']) {
            $title = '';
            if (isset($element['#options'][$key]['title']) && is_array($element['#options'][$key]['title'])) {
              if (!empty($element['#options'][$key]['title']['data']['#title'])) {
                $title = new TranslatableMarkup('Update @title', array(
                  '@title' => $element['#options'][$key]['title']['data']['#title'],
                ));
              }
            }
            $element[$key] = array(
              '#type' => 'checkbox',
              '#title' => $title,
              '#title_display' => 'invisible',
              '#return_value' => $key,
              '#default_value' => isset($value[$key]) ? $key : NULL,
              '#attributes' => $element['#attributes'],
            );
          }
          else {

            // Generate the parents as the autogenerator does, so we will have a
            // unique id for each radio button.
            $parents_for_id = array_merge($element['#parents'], array(
              $key,
            ));
            $element[$key] = array(
              '#type' => 'radio',
              '#title' => '',
              '#return_value' => $key,
              '#default_value' => $element['#default_value'] == $key ? $key : NULL,
              '#attributes' => $element['#attributes'],
              '#parents' => $element['#parents'],
              '#id' => HtmlUtility::getUniqueId('edit-' . implode('-', $parents_for_id)),
              '#ajax' => isset($element['#ajax']) ? $element['#ajax'] : NULL,
            );
          }
          if (isset($element['#options'][$key]['#weight'])) {
            $element[$key]['#weight'] = $element['#options'][$key]['#weight'];
          }
        }
      }
    }
    else {
      $element['#value'] = array();
    }
    return $element;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
FormElement::processAutocomplete public static function Adds autocomplete functionality to elements.
FormElement::processPattern public static function #process callback for #pattern form element property.
FormElement::validatePattern public static function #element_validate callback for #pattern form element property.
PluginBase::$configuration protected property Configuration information passed into the plugin. 2
PluginBase::$pluginDefinition protected property The plugin implementation definition.
PluginBase::$pluginId protected property The plugin_id.
PluginBase::DERIVATIVE_SEPARATOR constant A string which is used to separate base plugin IDs from the derivative ID.
PluginBase::getBaseId public function Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface::getBaseId
PluginBase::getDerivativeId public function Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface::getDerivativeId
PluginBase::getPluginDefinition public function Gets the definition of the plugin implementation. Overrides PluginInspectionInterface::getPluginDefinition
PluginBase::getPluginId public function Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface::getPluginId
PluginBase::__construct public function Constructs a Drupal\Component\Plugin\PluginBase object. 69
RenderElement::preRenderAjaxForm public static function Adds Ajax information about an element to communicate with JavaScript.
RenderElement::preRenderGroup public static function Adds members of this group as actual elements for rendering.
RenderElement::processAjaxForm public static function Form element processing handler for the #ajax form property.
RenderElement::processGroup public static function Arranges elements into groups.
RenderElement::setAttributes public static function Sets a form element's class attribute. Overrides ElementInterface::setAttributes
StringTranslationTrait::$stringTranslation protected property The string translation service.
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.
Table::preRenderTable public static function #pre_render callback to transform children of an element of #type 'table'.
Table::processTable public static function #process callback for #type 'table' to add tableselect support.
Table::validateTable public static function #element_validate callback for #type 'table'.
Tableselect::getInfo public function Returns the element properties for this element. Overrides Table::getInfo
Tableselect::preRenderTableselect public static function Prepares a 'tableselect' #type element for rendering.
Tableselect::processTableselect public static function Creates checkbox or radio elements to populate a tableselect table.
Tableselect::valueCallback public static function Determines how user input is mapped to an element's #value property. Overrides Table::valueCallback