web-dev-qa-db-fra.com

Quelle est la meilleure pratique pour afficher les champs d'un nœud dans différentes régions?

En D7, nous avions l'habitude de créer une vue pour les nœuds, chaque champ ayant son propre affichage. Chaque affichage crée un bloc à placer dans n'importe quelle région du site. Mais bien sûr, les vues sont lourdes en SQL.

Maintenant, Drupal 8 est tout de fantaisie. Quelle est la manière Drupal 8 d'afficher les champs d'un nœud dans différentes régions de la page?

Edit: ma tentative actuelle est de créer un module personnalisé qui fournit un bloc pour chaque champ spécifié.

7
Alex

Vous ne savez pas exactement pourquoi vous voulez que chaque champ soit un bloc distinct? C'est assez inefficace, si rien d'autre.

Pour avoir un ou deux blocs supplémentaires, vous pouvez utiliser un bloc de vue Entité fourni par le module ctools. Il prendra le nœud actuel et l'affichera dans un certain mode d'affichage. Bien sûr, ce sera pénible à maintenir si chaque champ est séparé, mais je ne vois pas vraiment pourquoi vous voudriez faire ça?

4
Berdir

Ctools dans D8 est livré avec un module expérimental appelé Blocs d'outils Chaos qui vous permettra de le faire dans n'importe quelle disposition de variante du gestionnaire de pages.

Ceci est très utile si vous créez une variante de nœud pour afficher un type de contenu.

Après l'avoir activé, vous pouvez ajouter n'importe quel champ du nœud en cours de visualisation. Vous verrez une liste complète des champs disponibles sous "Contenu" lorsque vous cliquez sur ajouter un bloc.

L'inconvénient, le module est expérimental et il n'y a pas beaucoup de documentation disponible.

Voici un fil conducteur à ce sujet https://www.drupal.org/node/280921

Page du module https://www.drupal.org/project/ctools

Je l'ai essayé moi-même et cela fonctionne très bien.

J'espère que cela vous aidera, vous ou toute personne à la recherche d'une solution pour ce type de scénario.

3
Nicolas Pinos

Quelle est la meilleure pratique pour afficher les champs d'un nœud dans différentes régions dans Drupal 8?

Je pense qu'il n'y a pas de meilleure pratique pour cela, peut-être même pas une bonne pratique, mais ce n'est pas impossible à faire, suivez quelques options

Pour moi, c'est la meilleure option: vous pouvez créer un bloc qui charge le nœud actuel et afficher le champ node_field souhaité. De cette façon, et vous pouvez gérer facilement via l'interface utilisateur (votre bloc avec 'node_type' select et 'field_name' select est facile et rapide à faire).


Commencer l'édition 1
Voici mon implémentation de ce bloc, testez et commentez les résultats

<?php
/**
 * @file
 * Contains \Drupal\ module_name\Plugin\Block\NodeFieldBlock.
 */

namespace Drupal\module_name\Plugin\Block;

use Drupal\Core\Block\BlockBase;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\field\Entity\FieldConfig;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;

/**
 * Provides a Filter by vocabulary terms block.
 *
 * @Block(
 *   id = "node_field_block",
 *   admin_label = @Translation("Node Field")
 * )
 */
class NodeFieldBlock extends BlockBase implements ContainerFactoryPluginInterface {
  /**
   * The Entity Type Manager.
   *
   * @var Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * The Entity Field Manager.
   *
   * @var Drupal\Core\Entity\EntityFieldManagerInterface
   */
  protected $entityFieldManager;

  /**
   * The Entity Display Repository.
   *
   * @var Drupal\Core\Entity\EntityDisplayRepository
   */
  protected $entityDisplayRepository;

  /**
   * Dependency injection through the constructor.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin ID for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_type_manager
   *   The Entity Type Manager.
   * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager
   *   The Entity Field Manager.
   * @param \Drupal\Core\Entity\EntityDisplayRepositoryInterface $entity_display_repository
   *   The Entity Display Repository.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition,
  EntityTypeManagerInterface $entity_type_manager,
  EntityFieldManagerInterface $entity_field_manager,
  EntityDisplayRepositoryInterface $entity_display_repository) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->entityTypeManager = $entity_type_manager;
    $this->entityFieldManager = $entity_field_manager;
    $this->entityDisplayRepository = $entity_display_repository;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('entity_type.manager'),
      $container->get('entity_field.manager'),
      $container->get('entity_display.repository')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return array(
      'node_type' => array_keys(node_type_get_names())[0],
      'view_mode' => 'default',
      'field' => '',
    );
  }

  /**
   * {@inheritdoc}
   */
  public function blockForm($form, FormStateInterface $form_state) {
    $types = node_type_get_names();
    $config = $this->configuration;
    if ($node_type = $form_state->getValue(array('settings', 'node_type'))) {
      $config['node_type'] = $node_type;
    }

    $form['node_type'] = array(
      '#title' => $this->t('Content type'),
      '#type' => 'select',
      '#options' => $types,
      '#default_value' => $config['node_type'],
      '#ajax' => array(
        'callback' => array(get_class($this), 'updateFieldList'),
        'wrapper' => 'edit-node-wrapper',
      ),
    );

    $form['options'] = array(
      '#type' => 'container',
      '#prefix' => '<div id="edit-node-wrapper">',
      '#suffix' => '</div>',
    );

    $form['options']['view_mode'] = array(
      '#title' => $this->t('View mode'),
      '#type' => 'select',
      '#multiple' => FALSE,
      '#options' => $this->getViewModes($config['node_type']),
      '#default_value' => $config['view_mode'],
    );

    $form['options']['field_list'] = array(
      '#title' => $this->t('Field list'),
      '#type' => 'select',
      '#multiple' => FALSE,
      '#options' =>  $this->getFieldList($config['node_type']),
      '#default_value' => $config['field'],
    );

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function blockSubmit($form, FormStateInterface $form_state) {
    $this->configuration['node_type'] = $form_state->getValue('node_type');
    $this->configuration['view_mode'] = $form_state->getValue(array('options', 'view_mode'));
    $this->configuration['field'] = $form_state->getValue(array('options', 'field_list'));
  }

  /**
   * {@inheritdoc}
   */
  public function build() {
    $config = $this->configuration;
    $build = array();
    if ($node = \Drupal::routeMatch()->getParameter('node')) {
      if ($config['node_type'] == $node->getType()) {
        if ($field = $node->get($config['field'])) {
          $build['field'] = $field->view($config['view_mode']);
        }
      }
    }
    return $build;
  }

  /**
   * {@inheritdoc}
   */
  public function getCacheTags() {
    if ($node = \Drupal::routeMatch()->getParameter('node')) {
      return Cache::mergeTags(parent::getCacheTags(), array('node:' . $node->id()));
    } else {
      return parent::getCacheTags();
    }
  }

  /**
   * {@inheritdoc}
   */
  public function getCacheContexts() {
    return Cache::mergeContexts(parent::getCacheContexts(), array('route'));
  }

  /**
  * Função que cria uma lista de fields de um node type.
  *
  * @param string $node_type
  *   O id do node type.
  * @return array
  *   Retorna a lista de campos do node type.
  */
  protected function getFieldList($node_type) {
    if (!empty($node_type)) {
      $list = $this->entityFieldManager->getFieldDefinitions('node', $node_type);
      foreach ($list as $id => $field) {
        if ($field instanceof FieldConfig) {
          $list[$id] = $field->label();
        } else {
          unset($list[$id]);
        }
      }
      return $list;
    }
    return array();
  }

  /**
  * Função que cria uma lista de view modes de um node type.
  *
  * @param string $node_type
  *   O id do node type.
  * @return array
  *   Retorna a lista de view mode do node type.
  */
  protected function getViewModes($node_type) {
    return $this->entityDisplayRepository->getViewModeOptionsByBundle('node', $node_type);
  }

  /**
   * Handles switching the node type selector.
   */
  public static function updateFieldList(&$form, FormStateInterface &$form_state, Request $request) {
    return $form['settings']['options'];
  }
}

Fin de l'édition 1


Ou ... obtenez votre champ dans preprocess_region Et chargez-le dans une var (c'est facile à démontrer).

function THEME_preprocess_region(&$variables) {
  //TODO: change for you region name
  if ($variables['region'] == 'sidebar_right') {
    if ($node = \Drupal::routeMatch()->getParameter('node')) {
      //TODO: change for you node type
      if ($node->getType() == 'article') {
        //If you need a flag for this type
        $variables['is_article'] = TRUE;
        //Here is your field
        $variables['node_field'] = $node->get('field_descricao')->view();
      }
    }
  }
}

Et utilisez dans votre fichier twig

{% if node_field %} 
  {{ node_field }}
{% endif %}

ATTENTION:
À l'avenir, vous ne pourrez pas supprimer ce champ, si vous le supprimez, cela cassera votre page. Explication: $node->get('field_descricao') n'évaluera aucune valeur nulle alors null->view() = page cassée. Même si vous vous en occupez, quelqu'un ou même vous pouvez l'oublier et ce sera un casse-tête pourquoi ces informations ne s'affichent plus.

2
Vagner

Le module Field Block fait à peu près ce que vous demandez. Il permet à n'importe quel champ dans n'importe quel type d'entité/bundle d'être affiché sous forme de bloc dans la région de votre choix.

1
NewZeal

par exemple, nous avons un champ "barre latérale" pour les nœuds. bien sûr, le contenu de ce champ doit être rendu en dehors du "contenu" normal, dans une région différente. - Alex Il y a 18 heures

Au lieu d'utiliser la disposition du thème et la région de la barre latérale, vous pouvez utiliser l'un des modules suivants et créer une disposition de panneau ou de suite d'affichage avec une région de la barre latérale. Ensuite, vous pouvez insérer les champs de noeud et autres blocs dont vous avez besoin dans la barre latérale et sur les autres régions que vous créez.

Panneaux

Le module Panneaux permet à un administrateur de site de créer des mises en page personnalisées pour plusieurs utilisations. À la base, il s'agit d'un gestionnaire de contenu par glisser-déposer qui vous permet de concevoir visuellement une mise en page et de placer du contenu dans cette mise en page. L'intégration avec d'autres systèmes vous permet de créer des nœuds qui l'utilisent, des pages de destination qui l'utilisent et même de remplacer les pages système telles que la taxonomie et la page de nœud afin que vous puissiez personnaliser la mise en page de votre site avec des autorisations très fines.

Suite d'affichage

Display Suite vous permet de prendre le contrôle total de la façon dont votre contenu est affiché à l'aide d'une interface glisser-déposer. Organisez vos nœuds, vues, commentaires, données utilisateur, etc. comme vous le souhaitez sans avoir à vous frayer un chemin à travers des dizaines de fichiers modèles.

1
No Sssweat

Si vous souhaitez utiliser la fonction d'édition rapide, vous pouvez créer et utiliser différents modes d'affichage via l'interface utilisateur (sous Structure/Modes d'affichage/Modes d'affichage). C'est à dire. vous n'êtes pas limité uniquement aux modes Teaser et Full view, par exemple. Et vous pouvez également utiliser vos modes d'affichage personnalisés dans les vues. Et le contenu rendu de cette manière aura tous les liens contextuels requis.

0
Stanislav Agapov