Создаем свой кастомный плагин Style – Темизация Views в Drupal 8

в 8:27, , рубрики: drupal, drupal 8, module, php, style, theming, views

Модуль Views (Представления) является составляющей ядра Drupal 8. На сегодняшний день об этом известно всем. Twig – это новый обработчик шаблонов в Drupal 8. Об этом нам тоже уже известно. Но как же программно взаимодействовать с модулем Views, для того чтобы темизировать View с использованием Twig? Кроме перекрывания шаблонов, как это происходит в любой другой системе модулей, у нас есть более мощная альтернатива в виде Views плагинов (Display, Style, Row и Field).

В данной статье мы разберемся, как в Drupal 8 создать Style плагин для Views. Мы используем разметку вкладок Bootstrap и реализуем вкладочный вывод наших результатов Views. В конфигурации Views, настройки Style позволят нам определить, какое поле будет использоваться как копия вкладочной навигации, и оставлять видимыми в соответствующих вкладках остальные поля. В целом, каждый результат View будет представлять собой вкладку, поэтому такой пример не подойдет для представлений, у которых слишком много результатов. Наша цель – продемонстрировать процесс создания собственного Style плагина в Drupal 8.

Мы не будем вдаваться в подробности того, как вы можете использовать Bootstrap в своих проектах. Но вы можете ознакомиться с документацией или некоторыми статьями, где описывается, как сделать так, чтобы на странице анонимного пользователя загружалась jQuery. И если вы хотите посмотреть на написанный нами код раньше времени, то можете найти его в этом репозитории в файле Demo module.

Что такое Style плагин?

Style плагин отвечает за передачу списков. Яркими примерами Style плагинов являются Неформатированный список, Список HTML, Таблица или Сетка. Их использует плагин Display, а они в свою очередь используют плагины Row, которые представляют один пункт списка.

В Drupal 8, все типы плагинов Views построены с использованием новой системы плагинов и имеют общий функционал (все они наследуются из одного и того же PluginBase).

Давайте создадим такой же Style плагин, который может быть использован большинством типов Display (Page, Block и т.д) и который использует плагин Field.

Style плагин Вкладки Bootstrap

Первый шаг – это создание нашего класса плагина в папке Plugin/views/style нашего модуля:

namespace DrupaldemoPluginviewsstyle;
use DrupalCoreFormFormStateInterface;
use DrupalviewsPluginviewsstyleStylePluginBase;

/**
 * Views стиль, который передает разметку для Bootstrap вкладок.
 *
 * @ingroup views_style_plugins
 *
 * @ViewsStyle(
 *   id = "bootstrap_tabs",
 *   title = @Translation("Bootstrap Tabs"),
 *   help = @Translation("Uses the Bootstrap Tabs component."),
 *   theme = "demo_bootstrap_tabs",
 *   display_types = {"normal"}
 * )
 */
class BootstrapTabs extends StylePluginBase {

  /**
   * Разрешает ли этот Style плагин Row плагины?
   *
   * @var bool
   */
  protected $usesRowPlugin = TRUE;

  /**
   * Поддерживает ли Style плагин группировку строк?
   *
   * @var bool
   */
  protected $usesGrouping = FALSE;

  /**
   * {@inheritdoc}
   */
  protected function defineOptions() {
    $options = parent::defineOptions();
    $options['tab_nav_field'] = array('default' => '');
    return $options;
  }

  /**
   * {@inheritdoc}
   */
  public function buildOptionsForm(&$form, FormStateInterface $form_state) {
    parent::buildOptionsForm($form, $form_state);
    $options = $this->displayHandler->getFieldLabels(TRUE);
    $form['tab_nav_field'] = array(
      '#title' => $this->t('The tab navigation field'),
      '#description' => $this->t('Select the field that will be used as the tab navigation. The rest of the fields will show up in the tab content.'),
      '#type' => 'select',
      '#default_value' => $this->options['tab_nav_field'],
      '#options' => $options,
    );
  }
}

Плагин Drupal, который мы создадим – это ViewsStyle с кое-какими базовыми данными о нем, переданными в аннотации. Не говоря о самых очевидных данных, у нас есть ключевые слова theme и display_types, о которых стоит упомянуть. Theme объявляет какую функцию темы будет использовать плагин для передачи данных, а display_types объявляет, каким видом плагинов Display может использоваться этот Style (в нашем случае все типы Display, если других не определено: normal). Если хотите узнать более подробную информацию о всех возможных конфигурациях Annotation, ознакомьтесь с DrupalviewsAnnotationViewsStyle класса Annotation.

Используя два свойства класса мы объявили, что наш плагин использует Row плагины, но не разрешает группирование. Убедитесь, что вы проверили все родительские и учли другие похожие опции. Например, класс, который мы наследуем, уже объявил, что поля Views могут быть использованы с плагином Style.

Как мы уже говорили ранее, используя два метода, мы создаем опцию плагина и элемент формы, которые могут определить, какое поле должно задействоваться в качестве навигации вкладки. Используя обработчик текущего состояния ($this->displayHandler), мы можем загрузить все доступные поля View, которые добавил движок сайта. И этот новый элемент формы будет доступен в форме настроек Style:

image

Поскольку мы наследуем с класса StylePluginBase, больше ничего делать не нужно. Для вывода разметки мы можем положиться на тему demo_bootstrap_tabs, которая получает подходящие переменные с исполненного View. Если сильно хочется, мы можем переопределить методы и добавить больше переменных, изменить тему и т.д. Но и параметры по умолчанию нам отлично подходят, а особенно, потому что мы реализуем препроцессор для обработки переменных, которые получает шаблон.

Тема

Самое время определить тему demo_bootstrap_tabs , как мы это делаем обычно (внутри нашего файла .module):

/**
 * Implements hook_theme().
 */
function demo_theme($existing, $type, $theme, $path) {
  return array(
    'demo_bootstrap_tabs' => array(
      'variables' => array('view' => NULL, 'rows' => NULL),
      'path' => drupal_get_path('module', 'demo') . '/templates',
    ),
  );
}

Плагин Style по умолчанию передает шаблону объект $view и результат $rows . Обработка этих переменных (если это необходимо) перед тем, как передать шаблону – это задание препроцессора.

/**
 * Подготовка переменных для шаблона представления demo_bootstrap_tabs.
 *
 * Шаблон: demo-bootstrap-tabs.html.twig.
 *
 * @param array $variables
 *   Ассоциативный массив содержит:
 *   - view: объект view.
 *   - row: массив пунктов rows. Каждый row – это массив из контента.
 */
function template_preprocess_demo_bootstrap_tabs(&$variables) {
  $view = $variables['view'];
  $rows = $variables['rows'];
  $variables['nav'] = array();

  // Подготовка навигации вкладок.
  $field = $view->style_plugin->options['tab_nav_field'];
  if (!$field || !isset($view->field[$field])) {
    template_preprocess_views_view_unformatted($variables);
    return;
  }

  $nav = array();
  foreach ($rows as $id => $row) {
    $nav[$id] = array(
      '#theme' => 'views_view_field',
      '#view' => $view,
      '#field' => $view->field[$field],
      '#row' => $row['#row'],
    );
  }

  template_preprocess_views_view_unformatted($variables);
  $variables['nav'] = $nav;
}

Что же происходит здесь? Во-первых, мы проверяем настройки плагина Style на предмет того, было ли использовано имя поля (того, которое было выбрано при конфигурировании View). Если нет, мы вызываем return, но только после того, как препроцессор выполнит функцию template_preprocess_views_view_unformatted. Далее, по результатам Views проходит цикл, и, в итоге, создается массив контента для нашей вкладочной навигации. Для этого, мы используем функцию темы views_view_field для того, чтобы передать выбранное поле. Наконец, мы передаем этот массив шаблону и запускаем препроцессор стиля неформатированного списка.

Шаблон

В Drupal 8 больше нет функций тем, теперь все обрабатывается в шаблонах Twig. Давайте посмотрим, как файл demo-bootstrap-tabs.html.twig выглядит в нашей папке шаблонов модуля:

<div>
    <!-- Nav tabs -->
    <ul class="nav nav-tabs" role="tablist">
        {% for tab in nav %}
            {% set active = '' %}
            {% if loop.index0 == 0 %}
                {% set active = 'active' %}
            {% endif %}
            <li role="presentation" class="{{ active }}"><a href="#tab-{{ loop.index0 }}" aria-controls="profile" role="tab" data-toggle="tab">{{ tab }}</a></li>
        {% endfor %}
    </ul>

    <!-- Tab panes -->
    <div class="tab-content">
        {% for row in rows %}
            {% set active = '' %}
            {% if loop.index0 == 0 %}
                {% set active = 'active' %}
            {% endif %}
            <div role="tabpanel" class="tab-pane {{ active }}" id="tab-{{ loop.index0 }}">{{ row.content }}</div>
        {% endfor %}
    </div>
</div>

Как вы видите, это необходимая разметка для Bootstrap вкладок. Конечно, она не будет работать, если вы не загрузили в свою тему соответствующие стили и скрипты Bootstrap.

Первое, что мы передаем – это пункты навигации вкладок (из нашей переменной nav). Когда цикл перебирает этот массив, мы также извлекаем пользу из значения индекса цикла для того чтобы сделать первый пункт активным значением по умолчанию, а также для того, чтобы у нас была возможность нацеливаться на окна контента вкладок, используя уникальные ID. Что же касается реального значения пунктов, мы просто выводим передаваемый массив, который был создан в препроцессоре, и Drupal занимается его передачей. С учетом изложенного, возможно, хорошей идеей будет убедиться, что поле, которое вы здесь используете, относительно короткое, без ссылки и основной разметки. Названия, возможно, будут работать нормально. Но тут дело в соответствующей конфигурации View.

Внизу навигации, мы передаем актуальные rows, используя тот же индекс цикла для того, чтобы установить по умолчанию первый row как активную панель вкладки и уникально обозначить их, чтобы выше созданная навигация могла контролировать их видимость. Насчет контента, мы передаем полностью переменную row.content (которая была подготовлена внутри template_preprocess_views_view_unformatted), в которой хранятся все поля нашего View. И если мы не хотим включать поле, которое мы использовали для навигации, мы можем просто исключить его из показа в конфигурации View. Это поле по-прежнему будет появляться в навигации (потому что мы его там поместили), но не будет появляться в основной панели вкладки.

Заключение

Ну вот и все. Views Style плагин для вывода результатов View в виде Bootstrap вкладок. Все, что нам необходимо сейчас – это убедиться, что зависимости Bootstrap загружены и конфигурируют наш View для использования Style плагина. Имейте в виду, что такой способ не подходит для Views с большим количеством результатов, и служит только в качестве примера создания плагинов Style.

Данная статья является переводом статьи "Theming Views in Drupal 8 – Custom Style Plugins".

Автор: helender

Источник

Поделиться

* - обязательные к заполнению поля