Как сделать опредленный режим отображения ноды в модальном окне.

23 ноября 2020 в 18:28
Аватар пользователя VasyOK VasyOK 0 33

Вывожу ноду в модальном окне через ссылку:
<a class="use-ajax"  data-dialog-type="modal" href="/mynode">Ссылка </a>

Можно ли, чтобы в модульном окне открывался определенный дисплей (тизер) ноды, а переходя на ноду (открытие ссылки в новой вкладке или новом окне) уже был другой дисплей ?

В D7 через colorbox_node это было возможно.

Комментарии

Судя по всему - невозможно и нода будет отображаться в default view mode. Однако, навскидку есть некоторые программные варианты.

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

23 ноября 2020 в 19:22

Вполне логично, что так работает в контексте Modal API, т.к. вы в ссылке указываете открыть ноду - путь к ноде. Этот роут ведет на ноду в default (full).

Т.е. чтобы открыть что-то, надо чтобы у него был роут. Нету - можно создать.

Есть даже контриб для этого
https://www.drupal.org/project/view_mode_page

23 ноября 2020 в 20:01

С этим модуль можно вывести по одной ссылке разные дисплеи в модале и без модала?
Пока что я вижу, что модуль задает страницу типа /%/teaser т.е. это уже другая ссылка. Или я не дочитал инструкцию?

24 ноября 2020 в 0:33

модуль не пробовал, но по описанию он добавляет роуты нужные тебе.
А дальше, хочешь в модал, хочешь не в модал

24 ноября 2020 в 0:35

vlucas wrote: С этим модуль можно вывести по одной ссылке разные дисплеи в модале и без модала?

Нет, ссылки будут отличаться для каждого дополнительного дисплея.
Пример:
mysite.com/mynode - дисплей 'default '
mysite.com/mynode/summary - дисплей 'summary'

Если прям очень необходимо, чтобы оба дисплея отображались по одной ссылке, то без программных костылей не обойтись - чтобы отделить AJAX-запрос (который суть модал и должен иметь отдельный view mode) от обычного запроса. Например, читать состояние серверной переменной $_SERVER['HTTP_X_REQUESTED_WITH'] и, если она установлена, то менять view mode.

Например, можно сбацать имплементацию хука hook_entity_view_mode_alter и устанавливать view mode 'по желанию', как-то так:

<?php
function YOUR_MODULE_entity_view_mode_alter(&$view_modeDrupal\Core\Entity\EntityInterface $entity$context) {
  if (
$entity->getEntityTypeId() == 'node' && $entity->bundle() == 'my_node_type' && isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
    
$view_mode 'MY_CUSTOM VIEW MODE';
  }
}
?>
24 ноября 2020 в 3:38

ну я про это ещё с первого комментария пишу ))
Modal API никак не связан с дисплеями того что он открывает. Ему вообще по барабану что открывать, что дадите )

24 ноября 2020 в 12:18

vlucas wrote: ну я про это ещё с первого комментария пишу ))

Про что именно?

Васька, видимо, интересует (полагаю, по шаманским соображениям SEO или по каким-то другим сакральным причинам) есть ли возможность использовать один и тот же URL для разных режимов отображения ноды.
И (имхо) без программных решений в этом случае точно не обойтись.

24 ноября 2020 в 16:43

Тут явно не сеошные соображения, а здравый смысл - во всплывашке контент должен быть немного упрощённый, но если кто-то нажмёт всплывашку колёсиком, то ему должна открыться целая нода, как ни в чём не бывало.

24 ноября 2020 в 17:05

Совершенно верно. Меня это интересует именно из здравого смысла. Сеошники меня не поймут, если будут адреса типа /*/teaser да и не нужны мне такие адреса.

24 ноября 2020 в 17:13

Не думал в этом аспекте. Или Васёк не очень понятно изложил суть задачи.
Действительно, тогда даже странно, почему не предусмотрено штатных механизмов выбора view mode на этот случай.

24 ноября 2020 в 18:34

Да не имеет это отношение к Modal API!
Цель - вывести что-то (абстрагируемся от конкретно чего - что правильно) в модальном окне. Это вовсе не сущность может быть

24 ноября 2020 в 19:06

Ну это как бы всё понятно.
Но какой-то признак AJAX-запроса (входящий на целевой контроллер) можно было обеспечить. Соответственно, чтобы и canonical-роут нод мог бы его читать и предлагать выбор из режимов отображения. Задачка-то вроде получается из востребованных.

24 ноября 2020 в 20:15

OldWarrior wrote: Но какой-то признак AJAX-запроса (входящий на целевой контроллер) можно было обеспечить

Можно добавить какой-нибудь кастомный заголовок в запрос, или же вызывать его, например, методом POST, или же записать что-нибудь в куку, а после ответа - почистить, или же просто добавить к урлу get-параметр.
Но в любом случае, придется писать кастомный js, который бы это делал.

Поэтому, в таком случае, проще всего было бы сделать ссылку вида
<a href="/some/alias" data-modal-href="/modal/node/{nid}"> и по click'у делать запрос по урлу в data-modal-href
соотвественно, по роуту /modal/node/{nid} - отдавать рендер ноды без регионов.

24 ноября 2020 в 22:22

Andruxa wrote: Можно добавить какой-нибудь кастомный заголовок в запрос... и т.д.

Да зачем так усложнять, Андрюха?
"Всё уже украдено до нас" ©, т.е.:
Symfony\Component\HttpFoundation\Request::isXmlHttpRequest() либо просто
<?php if ($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest'){...} ?>

Остаётся "научить" контроллер canonical-роута читать этот флаг и понимать, когда нужно отдавать сущность в другом view mode (или просто юзать вышеприведённый hook_entity_view_mode_alter), а также программно добавить новый специальный режим отображения а-ля "ajax_modal" для связывания с AJAX-запросами. Или вообще добавить галку "Use on AJAX request only" в настройки каждого дисплея (что будет указывать на то, что данный дисплей обрабатывает исключительно AJAX-запросы).

И то и другое - в общем-то несколько строк PHP-кода. Это если говорить о патче ядра или новом контрибе.

Andruxa wrote: Поэтому, в таком случае, проще всего было бы сделать ссылку вида
<a href="/some/alias" data-modal-href="/modal/node/{nid}">...

Преимущество этой идеи в том, что можно указывать разные целевые AJAX-роуты даже для одного и того же типа материала (допустим, когда несколько типов модальных окон для нод и вызываются они каждый своей ссылкой). Но тогда и эти роуты нужно, разумеется, писать программно для каждого индивидуального случая. Либо (как предлагал vlucas выше) юзать https://www.drupal.org/project/view_mode_page.

25 ноября 2020 в 3:58

OldWarrior wrote: HTTP_X_REQUESTED_WITH

Меня терзают смутные сомнения.
Далеко не всегда вебсервер предоставляет это значение, особенно в случае проксирования запросов nginx -> apache. Там в конфигах вирт.хостов порою такое написано - обнять и плакать.
Да и идея отдачи разного контента по одному урлу - попахивает клоакингом.

25 ноября 2020 в 9:36

Andruxa wrote: Далеко не всегда вебсервер предоставляет это значение, особенно в случае проксирования запросов nginx -> apache.

Возможно это и так, но под апачем у меня пока не было проблем (я использую это решение на одной из своих самописных систем). Хотя в целом - да, всё же следует учитывать и то, что переменная может быть не выставлена сервером. Ниже gun_dose предлагает иной способ идентификации AJAX-запросов.

Andruxa wrote: Да и идея отдачи разного контента по одному урлу - попахивает клоакингом.

Это не то, чтобы совсем разный контент - скорее разные версии одного материала. Но если вспомнить страницы терминов (или даже просто /node) - там динамический контент на одном урле может меняться ежеминутно. Ну это так, мысли.

25 ноября 2020 в 18:03

В D7 через colorbox_node это было возможно.

Уточни, каким образом...

Так можно же через шаблонный if (!$page) подсунуть разницу для модалки и full-mode...
Пихай туда что хочешь, хоть любимую вьюху.

P.S. Хотя, для ссылки use-ajax-modal это может и не прокатит.

24 ноября 2020 в 7:36

Нет, если модал выводится по определенной ссылке, я могу и без всяких модулей это накликать.
Совершенно верно: "необходимо, чтобы оба дисплея отображались по одной ссылке"

adano, уточняю. В настройках отображения материала есть дисплей Colorbox - в нем и настривается.

24 ноября 2020 в 12:14

Короче, я тут вспомнил одну вещь, которая ещё со времён семёрки не менялась. Для ссылок с классом use-ajax можно в качестве последнего компонента пути указывать "nojs", типа /node/1/nojs. Друпаловский аякс обрабатывает эти ссылки таким образом, что запрос отправляется на урл /node/1/ajax. И издревле (как минимум со времён семёрки) пути таких контроллеров принято объявлять как /node/{id}/{ajax}. И по второму параметру можно определять, аяксовый запрос или простой, и отдавать соответственно аякс-респонс либо редирект на ноду. Редирект конечно может быть не очень красиво, но можно на ссылки повесить nofollow.

Вторая вещь, которая касается ссылок с классом use-ajax: к урлу аяксового запроса добавляется параметр _wrapper_format=drupal_ajax. То есть если даже запрашивать ноду по её обычному урлу, то всё равно есть простой и понятный признак, чтобы идентифицировать запрос, как аяксовый. То есть, можно воспользоваться hook_entity_view_mode_alter, как предлагали выше, а в хуке уже смотреть гет-параметры запроса и подменять вью-мод.

25 ноября 2020 в 10:26

gun_dose wrote: Вторая вещь, которая касается ссылок с классом use-ajax: к урлу аяксового запроса добавляется параметр _wrapper_format=drupal_ajax. То есть если даже запрашивать ноду по её обычному урлу, то всё равно есть простой и понятный признак, чтобы идентифицировать запрос, как аяксовый. То есть, можно воспользоваться hook_entity_view_mode_alter, как предлагали выше, а в хуке уже смотреть гет-параметры запр

По-моему, тоже вполне себе рабочее решение.
Тем более, что выше уже указывают на то, что отдача разного контента по одному урлу может быть аморальна. А тут вроде как урлы разные.

25 ноября 2020 в 17:55

Когда мне нужно было оформить вебформу в модалке по своему, а страничку по своему, я делал так:

Ссылка в HTML:

<a href="/form/callback" class="btn use-ajax" data-dialog-type="modal" rel="nofollow">Обратный звонок</a>

THEME.theme

<?php
function HOOK_theme_suggestions_alter(array &$suggestions, array $vars$hook) {
  if (
in_array($hook, array('webform'))) {

    

$wrapper_format = \Drupal::request()->query->get('_wrapper_format');
    
$is_modal = \Drupal::request()->query->get('is_modal');

    if (

$wrapper_format == 'drupal_modal' || $is_modal) {
      
$suggestions[] = $hook '__' 'modal';

      return;
    }

    

$params = \Drupal::routeMatch()->getParameters();
    if (
$params->get('webform')) {
      
$suggestions[] = $hook '__' 'full';
    }
  }
}
?>

При ajax загрузки модального окна передавал Get параметр

template.js:

  // Update Drupal.Ajax.prototype.beforeSend only once.
  if (typeof Drupal.Ajax !== 'undefined' && typeof Drupal.Ajax.prototype.beforeSubmitOriginal === 'undefined') {
    Drupal.Ajax.prototype.beforeSubmitOriginal = Drupal.Ajax.prototype.beforeSubmit;
    Drupal.Ajax.prototype.beforeSubmit = function (form_values, element_settings, options) {
      if (this.$form.hasClass('webform-modal')) {
        options.url += '&is_modal=1';
      }
      return this.beforeSubmitOriginal();
    };
  }

После чего смог нормально использовать разные Twig шаблоны для модалки и странички:

  • webform--modal.html.twig
  • webform--full.html.twig

Не претендую на правильность, но работает как часы)

P.s. в 7-ке было проще с колорбоксом. Можно было условия на view_mode прописать в самом файле темизации.

25 ноября 2020 в 14:43

Видимо пришлось вернуться к теме вопроса.
Много сверху всего написано, я так сходу в это не въеду, извините за повторы.

Итак я могу сформитровать ссылку вида <a href="/some/alias" data-modal-href="/modal/node/{nid}">, где /modal/node/{nid} - путь сформированный вьюхой (для этого же не принципиален модуль view_mode_page?)

И как выводить в модале именно то что, что в data-modal-href ?

23 декабря 2020 в 15:09

Как-то так:

$("a[data-modal-href]").click(function(){
  $.colorbox({href: $(this).data("modal-href")});
});

мог ошибиться, давно не брал в руки джаваскрпт.

23 декабря 2020 в 22:11

А чем попап сделан?

в общем случае как-то так:

$.get($(this).data("modal-href"), function(data){
  $("popup-content-selector").html(data);
  $("popup").trigger("popup");
});
24 декабря 2020 в 12:02

Попап сделан через ui-dialog, который встроен в Drupal. Эта конструкция работает по умолчанию (в темах ядра):
<a class="use-ajax"  data-dialog-type="modal" href="/mynode">Ссылка </a>

24 декабря 2020 в 12:04

что-то не получается через "html(data).dialog()"

Спсциалисты по JS и ui-dialog, посдскажите.

Ссылка
<a class="use-ajax"  data-dialog-type="modal" href="/mynode" data-modal-href="/modal/node/1">Ссылка </a>

Как сделать, чтобы по клику открывалось то, что в data-modal-href?

$("a[data-modal-href]").click(function() {
                var url = $(this).attr("data-modal-href");                
                /*тут вроде строчку дописать. как открыть ссылку с полученным url?*/
});
25 декабря 2020 в 18:15

Еще так пробовал

 $("a[data-modal-href]").click(function() {
                url = $(this).attr("data-modal-href");
                $('<div class="ui-dialog"></div>').load(url).dialog();
});

Оно, то работает, но выводит вместе с контентом еще и регионы темы. + не может нормально завершить операцию.

26 декабря 2020 в 3:14