Помощь начинающим веб
разработчикам

Drupal 8 - Подгрузка контента с использованием Ajax API

29.08.2017

В предыдущей статье мы с вами подгружали контент с использованием плагина Jquery – jScroll, сегодня мы займемся тем же самым, а именно подгрузкой контента, но только с использованием Ajax API Drupal 8.

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

По сути, реализация достаточно простая. Все что нам нужно это обычная реализация ajax ссылки, callback которой будет принимать NID ноды и отдавать отрендеренный результат в указанный селектор DOM дерева. Итак, как всегда, вся реализация будет в модуле, в моем случае он будет называться – load_content.

Файл load_content.info.yml

name: Load Content
description: Пример подгрузки статей сайта с использование Ajax API
core: 8.x
type: module

Далее реализуем ajax ссылку, более подробно об этом можно почитать здесь, я не буду на этом останавливаться.

Файл маршрутизации – load_content.routing.yml

load_content.routing:
  path: '/load_content/{nid}'
  defaults:
    _title: 'Load content Ajax link'
    _controller: '\Drupal\load_content\Controller\LoadContentController::loadContent'
  requirements:
    _permission: 'access content'

Хочу заметить, что callback ajax ссылки должен принимать NID ноды, которую необходимо загрузить.

Файл контроллера – LoadContentController.php

<?php

namespace Drupal\load_content\Controller;

use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\ReplaceCommand;

use Drupal\Core\Controller\ControllerBase;

class LoadContentController extends ControllerBase{

  public function loadContent($nid) {

    # Get NID render
    $node = \Drupal::entityTypeManager()->getStorage('node')->load($nid);
    $node_view = render(\Drupal::entityTypeManager()->getViewBuilder('node')->view($node, 'full'));

    # New response
    $response = new AjaxResponse();

    # Commands Ajax
    $selector = '.load-content';
    $response->addCommand(new ReplaceCommand($selector, $node_view, $settings = NULL));

    # Return response
    return $response;

  }

}

Как вы могли заметить из файла контроллера, мы используем ajax команду – ReplaceCommand, она в свою очередь заменяет указанный селектор на указанное содержимое, в нашем случае отрендеренная нода, поэтому ссылку на подгрузку контента нам необходимо выводить уже после всей HTML разметки ноды. Про Ajax команды можно почитать здесь.

Так как ajax ссылка подгрузки контента у нас динамическая, то для нее создадим отдельную переменную, которую будем выводить в node.html.twig.

Файл load_content.module

<?php

use Drupal\Core\Url;

/**
 * @param $variables
 * Implements hook_preprocess_node
 */
function load_content_preprocess_node(&$variables){

  if($variables['view_mode'] == 'full'){

    # Default return content
    $output = '';

    # Type content
    $type_node = 'article';

    if($variables['elements']['#node']->getType() == $type_node){

      # Get NID node
      $nid = $variables['elements']['#node']->id();

      # Get prev NID node
      $query = \Drupal::database()->select('node', 'n');
      $query->addField('n', 'nid');
      $query->condition('n.type', $type_node);
      $query->condition('n.nid', $nid, '<');
      $query->orderBy('n.nid', 'DESC');
      $query->range(0, 1);
      $prev_nid = $query->execute()->fetchField();

      if($prev_nid){

        # Title Prev node
        $title = 'Prev station → ' .$variables['elements']['#node']->getTitle();

        # Create link
        $url = Url::fromRoute('load_content.routing', array('nid' => $prev_nid));
        $link = array(
          '#type' => 'link',
          '#url' => $url,
          '#title' => $title,
          '#attributes' => array(
            'class' => array('use-ajax', 'load-content'),
          ),
        );
        $output = render($link);
      }

    }

    # Add variable for NODE templates
    $variables['load_content_nid'] = $output;

  }

}

/**
 * @param $variables
 * Implements hook_preprocess_page()
 */
function load_content_preprocess_page(&$variables) {

  $logged_in = \Drupal::currentUser()->isAuthenticated();
  if(!$logged_in && isset($variables['node']) && $variables['node']->getType() == 'article'){
    # Add libraries for anonymous
    $libraries['#attached']['library'][] = 'core/drupal.ajax';
    render($libraries);
  }

}

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

Далее активируем модуль. Теперь, все что нам осталось, это вывести в шаблоне ноды нашу переменную, которая содержит ajax ссылку. Для этого открываем файл темы node.html.twig и пишем после всей HTML разметки вывод переменной:

{{ load_content_nid }}

Далее чистим кеш сайта и смотрим результат:

Drupal_8_ajax_load_content.png

На этом можно закончить.

Скачать используемый в примере модуль.

Скачать

Узнавай о новых статьях сайта - первым. Просто подпишись на рассылку.

Комментарии (2)

Profile picture for user Алексей
Александр
01.09.2017

Вот  у нас есть часть кода:

         '#attributes' => array(
            'class' => array('use-ajax', 'load-content'),
          ),

И мы в место load-content вставляем контент, переменную $node_view. Но интересует следующее load_content это же у нас класс, разве мы можем на место класса вставить контент?

Profile picture for user pantey
pantey
03.09.2017

а что нам мешает это делать ? Если хотите можете использовать ID - так наверное правильнее будет.

Добавить комментарий

- Оповестить о новом комментарии.
- Все комментарии
- Только мои комментарии