Score:1

Extend core select widget

tr flag

Please help with the following:

I need a new widget (just a slightly altered select) that can be setup from the UI by anyone. I have done the following:

  1. Created a new custom module and enabled it.

  2. Created a new widget.

<?php

namespace Drupal\filtered_select\Plugin\Field\FieldWidget;

use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\Plugin\Field\FieldWidget\OptionsSelectWidget;
use Drupal\Core\Form\FormStateInterface;

/**
 * Plugin implementation of the 'filtered_select' widget.
 *
 * @FieldWidget(
 *   id = "filtered_select",
 *   label = @Translation("Filtered Select"),
 *   field_types = {
 *      "entity_reference"
 *   },
 *   multiple_values = FALSE
 * )
 */
class FilteredSelectWidget extends OptionsSelectWidget {

  /**
   * {@inheritdoc}
   */
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
    $element = parent::formElement($items, $delta, $element, $form, $form_state);
    // Use the parent select functionality,
    // just switch the element.
    $element['#type'] = 'fselect';

    return $element;
  }

}

  1. Created new element so I can switch the theme. (not sure if this is necessary)
<?php

namespace Drupal\filtered_select\Element;

use Drupal\Core\Render\Element\Select;

/**
 * Provides the filtered select element.
 * 
 * @FormElement("fselect")
 */
class FilteredSelect extends Select {

  /**
   * {@inheritdoc}
   */
  public function getInfo() {
    $info = parent::getInfo();

    // Theme switch.
    $info['#theme'] = 'fselect';

    return $info;
  }
}

  1. It did not work otherwise so I also got a hook_theme up in my module file like this:
/**
 * Implements hook_theme().
 */
function filtered_select_theme($existing, $type, $theme, $path): array {
    return [
        'fselect' => [
            'render element' => 'element',
            'template' => 'fselect',
        ],
    ];
}
  
  1. I just copied the template from core into my custom module and it works in the sense that it prints the right template, I have not yet altered this one, I just want to get the same old core functionality working under another name first.

Issue: My new render element seems to be missing the options array and I can't figure out why. I've done really basic overwrites and I cannot understand why it does not build the options array.

Twig Var Dumps:

--- THIS IS THE CORE SELECT ---

array:15 [▼
  "element" =>array:41 [▶]
  "theme_hook_original" => "select"
  "attributes" =>Drupal\Core\Template\Attribute {#7543 ▶}
  "title_attributes" =>Drupal\Core\Template\Attribute {#7932 ▶}
  "content_attributes" =>Drupal\Core\Template\Attribute {#7896 ▶}
  "title_prefix" => []
  "title_suffix" => []
  "db_is_active" =>true
  "is_admin" =>true
  "logged_in" =>true
  "user" =>Drupal\Core\Session\AccountProxy {#2354 ▶}
  "directory" => "core/themes/seven"
  "options" =>array:3 [▼0 =>array:4 [▶]
    1 =>array:3 [▶]
    2 =>array:3 [▶]
  ]
  "#cache" =>array:1 [▶]
  "theme_hook_suggestions" => []
]

--- THIS IS MY 'NEW' Filtered Select ---

array:14 [▼
  "element" =>array:41 [▶]
  "theme_hook_original" => "fselect"
  "attributes" =>Drupal\Core\Template\Attribute {#7543 ▶}
  "title_attributes" =>Drupal\Core\Template\Attribute {#8034 ▶}
  "content_attributes" =>Drupal\Core\Template\Attribute {#7708 ▶}
  "title_prefix" => []
  "title_suffix" => []
  "db_is_active" =>true
  "is_admin" =>true
  "logged_in" =>true
  "user" =>Drupal\Core\Session\AccountProxy {#2354 ▶}
  "directory" => "core/themes/seven"
  "#cache" =>array:1 [▶]
  "theme_hook_suggestions" => []
]

As one can see, I'm missing the 'options' array and I cannot understand why. Please advise.

Score:1
cn flag

You are missing template_preprocess_select(). You could copy the code to your own preprocess hook for fselect or, which might be a better idea, extend select as base hook and use double underscores select__fselect for the extended template name. See How do I define a custom html.html.twig file?

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.