Allow Site Settings Block to select view_mode

Created on 18 September 2020, about 4 years ago
Updated 9 August 2024, about 2 months ago

Problem/Motivation

Site Settings provides 2 blocks, one is a rendered entity, the other is just plain field values, which is great, but limits the flexibility for site builders to control what is displayed and how.

Use case: I have a Site Setting type, Locations. In this type, I have an address field ( rendered as an address ) and a Geolocation field rendered as a Google Map. I have 3 view modes, Default, Address, and Map.

  • Default displays the address and map.
  • Address just displays the address.
  • Map just displays the map.

I want site builders to be able to place a map block in some contexts, and just an address block in other contexts. However, the Site Settings block only ever renders the default view_mode.

https://git.drupalcode.org/project/site_settings/-/blob/8.x-1.x/src/Plug...

$pre_render = $view_builder->view($entity, 'default');

Proposed resolution

Add a setting to the RenderedSiteSettingsBlock that allows for selecting any enabled view_mode for the selected bundle.

My thoughts are, add an AJAX callback on the BlockForm such that when a Site Setting Type is selected, a second select box is displayed with enabled view_modes for that Site Setting Type.

use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\ReplaceCommand;
use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
// Inject this service.
// ...
  public function defaultConfiguration() {
    return [
      'setting' => NULL,
      'label_display' => FALSE,
      'view_mode' => NULL,
    ] + parent::defaultConfiguration();
  }

 public function blockForm($form, FormStateInterface $form_state) {

    // Allow selection of a site settings entity type.
    $form['setting'] = [
      '#type' => 'entity_autocomplete',
      '#target_type' => 'site_setting_entity_type',
      '#title' => $this->t('Site setting type'),
      '#weight' => '20',
      '#required' => TRUE,
      // Add ajax callback
      '#ajax' => [
        'callback' => '::viewModeCallback',
        'event' => 'autocompleteclose change',
        'wrapper' => 'edit-view-mode',
      ],
    ];
    if (isset($this->configuration['setting']) && !empty($this->configuration['setting'])) {
      $setting_entity_type = $this->entityTypeManager
        ->getStorage('site_setting_entity_type')
        ->load($this->configuration['setting']);
      $form['setting']['#default_value'] = $setting_entity_type;

      // Load the view_mode widget if configuration 'view_mode' is set.
      $view_mode_default = NULL;
      if (isset($this->configuration['view_mode']) && !empty($this->configuration['view_mode'])) {
        $view_mode_default = $this->configuration['view_mode'];
      }
      array_push($form, $this->viewModeElement($setting_entity_type, $view_mode_default);
    }
    else {
      // Return empty div so we have a target container.
      $form['view_mode'] = [
        '#markup' => '<div class="view-mode"></div>',
        '#allowed_tags' => ['div'],
      ];
    }
    return $form;
  }

  public function getViewModes($entity_type) {
    $view_modes = $this->repository->getViewModeOptionsByBundle('site_setting_entity_type', $entity_type);
    return $view_modes;
  }

  public function viewModeCallback(array &$form, FormStateInterface $form_state) {
    $entity_type = $form_state->getValue('setting');
    $element = $this->viewModeElement($entity_type);
    return $element;
  }

  public function viewModeElement($entity_type = NULL, $default = NULL) {
    $view_modes = $this->getViewModes($entity_type);
    $options = $this->getViewModes($entity_type);
    if (is_array($options) && count($options) > 1) {
      $element['view_mode'] = [
        '#type' => 'select',
        '#title' => $this->t('Select View Mode'),
        '#options' => $options,
      ];
      if ($default != NULL) {
        $element['view_mode']['#default_value'] = $default;
      }
    }
    else {
      $element['view_mode'] = [
        '#type' => 'hidden',
        '#value' => ($default) ? $default : $options,
      ];
    }
    return $element;
  }

I haven't tested any of this, but I feel like it's the correct approach.

Remaining tasks

Build / test.

User interface changes

New field to select view mode.

API changes

Data model changes

Add a new setting for view mode.

✨ Feature request
Status

Fixed

Version

2.0

Component

Code

Created by

πŸ‡ΊπŸ‡ΈUnited States scottsawyer Atlanta

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

Production build 0.71.5 2024