Was ist die beste Vorgehensweise, um die Felder eines Knotens in verschiedenen Regionen anzuzeigen?

7

In D7 haben wir eine Ansicht für Knoten erstellt, wobei jedes Feld eine eigene Anzeige hat. Jede Anzeige erstellt einen Block, der in einer beliebigen Region der Site platziert werden kann. Aber Ansichten sind natürlich SQL-lastig.

Jetzt ist Drupal 8 alles andere als schick. Wie zeigt Drupal 8 die Felder eines Knotens in verschiedenen Bereichen der Seite an?

Bearbeiten: Mein aktueller Versuch besteht darin, ein benutzerdefiniertes Modul zu erstellen, das einen Block für jedes angegebene Feld bereitstellt.

Alex
quelle

Antworten:

4

Sie wissen nicht genau, warum Sie jedes einzelne Feld als separaten Block haben möchten? Das ist ziemlich ineffizient, wenn nichts anderes.

Um einen oder zwei zusätzliche Blöcke zu haben, können Sie einen Entitätsansichtsblock verwenden, der vom ctools-Modul bereitgestellt wird. Der aktuelle Knoten wird in einem bestimmten Ansichtsmodus angezeigt. Natürlich wird es schmerzhaft sein, das beizubehalten, wenn jedes Feld separat ist, aber ich verstehe nicht wirklich, warum Sie das tun möchten?

Berdir
quelle
Zum Beispiel haben wir ein Feld "Seitenleiste" für Knoten. Natürlich sollte der Inhalt dieses Feldes außerhalb des normalen "Inhalts" in einer anderen Region gerendert werden.
Alex
3

Ctools in D8 enthält ein experimentelles Modul namens Chaos-Werkzeugblöcke , mit dem Sie dies in jedem Seitenmanager- Variantenlayout tun können.

Dies ist sehr nützlich, wenn Sie eine Knotenvariante erstellen, um einen Inhaltstyp anzuzeigen.

Nachdem Sie es aktiviert haben, können Sie ein beliebiges Feld des angezeigten Knotens hinzufügen. Sie sehen eine vollständige Liste der unter "Inhalt" verfügbaren Felder, wenn Sie auf Block hinzufügen klicken.

Der Nachteil ist, dass das Modul experimentell ist und nicht viel Dokumentation verfügbar ist.

Hier ist ein aktiver Thread dazu https://www.drupal.org/node/2809213

Modulseite https://www.drupal.org/project/ctools

Ich habe es selbst versucht und es funktioniert gut.

Ich hoffe, dies hilft Ihnen oder jedem, der nach einer Lösung für diese Art von Szenario sucht.

Nicolas Pinos
quelle
2

Was ist die beste Vorgehensweise, um die Felder eines Knotens in verschiedenen Regionen in Drupal 8 anzuzeigen?

Ich denke, es gibt keine Best Practice dafür, vielleicht nicht einmal eine gute Practice, aber es ist nicht unmöglich, ein paar Optionen zu befolgen

Für mich ist dies die beste Option: Sie können einen Block erstellen, der den aktuellen Knoten lädt und Ihr gewünschtes Knotenfeld anzeigt. Auf diese Weise können Sie problemlos über die Benutzeroberfläche verwalten (Ihr Block mit 'node_type' select und 'field_name' select ist einfach und schnell zu erledigen).


Beginnen Sie mit der Bearbeitung 1
Hier meine Implementierung dieses Blocks, testen und kommentieren Sie bitte die Ergebnisse

<?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'];
  }
}

Edit beenden 1


Oder ... holen Sie Ihr Feld ein preprocess_regionund laden Sie eine Variable (dies ist leicht zu demonstrieren).

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();
      }
    }
  }
}

Und in Ihrer Zweigdatei verwenden

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

VORSICHT:
In Zukunft können Sie dieses Feld nicht mehr entfernen. Wenn Sie es entfernen, wird Ihre Seite beschädigt. Erläuterung: $node->get('field_descricao')wird keine Null auswerten, dann null->view()= kaputte Seite. Selbst wenn Sie sich darum kümmern, kann jemand oder sogar Sie dies vergessen und es wird Ihnen Kopfschmerzen bereiten, warum diese Informationen nicht mehr angezeigt werden.

Vagner
quelle
Alter, das ist eine kranke Antwort! Ich werde es später versuchen
Alex
Wie wäre es mit Leistung und Caching? ist das performant?
Alex
1
Das ist in Ordnung, in der Erstellungsphase wird nur ein Element gerendert (keine Suchvorgänge, keine Erstellungslisten ... nur prüfen, ob vorhanden), sonst nichts. Jede Route, auf der dieser Block erstellt wird ( getCacheContexts). Wenn ein Knoten mit einem bestimmten Typ vorhanden ist, wird ein Feld gerendert. Und ja, wenn Sie zum zweiten Mal besuchen, wird der Cache verwendet. Wenn Sie den Knoten ändern, wird Ihr Block neu erstellt ( getCacheTags). In diesem Fall (Blockabrufknoteninformationen) muss das Blockobjekt die Cache-Informationen überschreiben. Andernfalls wird Ihr Block nur einmal erstellt und überall verwendet.
Vagner
1

Zum Beispiel haben wir ein Feld "Seitenleiste" für Knoten. Natürlich sollte der Inhalt dieses Feldes außerhalb des normalen "Inhalts" in einer anderen Region gerendert werden. - Alex vor 18 Stunden

Anstatt das Layout und den Seitenleistenbereich des Themas zu verwenden, können Sie eines der folgenden Module verwenden und ein Panel- oder Display-Suite-Layout mit einem Seitenleistenbereich erstellen. Anschließend können Sie die benötigten Knotenfelder und anderen Blöcke in die Seitenleiste und in andere von Ihnen erstellte Regionen einfügen.

Panels

Mit dem Panel-Modul kann ein Site-Administrator benutzerdefinierte Layouts für mehrere Zwecke erstellen. Im Kern handelt es sich um einen Drag & Drop-Inhaltsmanager, mit dem Sie ein Layout visuell entwerfen und Inhalte in diesem Layout platzieren können. Durch die Integration in andere Systeme können Sie Knoten erstellen, die dies verwenden, Zielseiten, die dies verwenden, und sogar Systemseiten wie Taxonomie und die Knotenseite überschreiben, sodass Sie das Layout Ihrer Site mit sehr fein abgestimmten Berechtigungen anpassen können.

Display Suite

Mit der Display Suite können Sie die vollständige Kontrolle darüber übernehmen, wie Ihre Inhalte per Drag & Drop angezeigt werden. Ordnen Sie Ihre Knoten, Ansichten, Kommentare, Benutzerdaten usw. so an, wie Sie möchten, ohne sich durch Dutzende von Vorlagendateien arbeiten zu müssen.

Kein Sssweat
quelle
Ich kenne diese Module. sind sie performant? Ansichten zum Beispiel sind ziemlich SQL-schwer, da sie zusätzliche SQL-Abfragen ausführen, obwohl der Knoten bereits geladen ist
Alex
1
In der Vergangenheit haben sich diese Module mit dem Alter verbessert. Ich habe noch keine Leistungsmessungen für die D8-Versionen gesehen, aber beide werden von Unternehmen entwickelt und verwendet, die sich große Sorgen um die Leistung machen. Daher gehe ich davon aus, dass sie bald gebaut werden, wenn sie heute nicht so gut gebaut sind, wie sie sein könnten.
Akrosman
1

Das Feldblock- Modul macht so ziemlich das, was Sie verlangen. Damit kann jedes Feld in einem beliebigen Entitätstyp / Bundle als Block in der Region angezeigt werden, die Ihnen gefällt.

NewZeal
quelle
Leider erstellt es einen Block für jeden Inhaltstyp und jedes Feld, was zu vielen Blöcken führt: /
Alex
0

Wenn Sie die Schnellbearbeitungsfunktion verwenden möchten, können Sie verschiedene Ansichtsmodi über die Benutzeroberfläche erstellen und verwenden (unter Struktur / Anzeigemodi / Ansichtsmodi). Das heißt, Sie sind nicht nur auf die Modi Teaser und Vollansicht beschränkt. Sie können Ihre benutzerdefinierten Ansichtsmodi auch in Ansichten verwenden. Und so gerenderte Inhalte enthalten alle erforderlichen Kontextlinks.

Stanislav Agapov
quelle
Das heißt aber, ich müsste für jedes Feld einen Ansichtsmodus erstellen?
Alex
Nein, Sie können einen neuen Ansichtsmodus für Knoten erstellen und diesen auf der Registerkarte "Anzeige verwalten" des Inhaltstyps anpassen. Jeder Ansichtsmodus (als eine Reihe von Feldanzeigen betrachtet) kann separat von anderen eingestellt werden.
Stanislav Agapov
-1

In Drupal 7 habe ich genau das Gleiche getan wie in Alex: Ansichten erstellen, um Inhalte in Blöcken zu platzieren. Ich fand diesen Thread auf der Suche nach einer Möglichkeit, QuickEdit zum Laufen zu bringen.
Display Suite und ViewModes scheinen die Antwort zu sein.

Dies scheint mir der sauberste Weg zu sein: Mit der Drupal 8-Version von Display Suite können Sie Felder von Knoten zu Blöcken hinzufügen.
Vollständige Anweisungen finden Sie unter https://www.drupal.org/node/2754967 . Diese Methode erspart das Erstellen einer Reihe von Ansichten und ermöglicht die Inline-Bearbeitung.

Roo
quelle