it-swarm.com.de

Wie erhalte ich den Kontextknoten in einem benutzerdefinierten Block in einer Ansichtsliste?

Ich habe eine Ansicht, die alle Bilder des Inhaltstyps photo anzeigt. Ich habe in dieser Ansicht einige Felder für die Anzeige festgelegt.

So rendere ich die Liste der Bilder:

Ansichten-Ansichtsfelder - photo.html

<figure class="element-item {{ fields['name'].content|lower }}">
    <a href="{{ fields['field_photo_1'].content|lower }}">
        <img src="{{ fields['field_photo'].content }}"/>
    </a>
    <figcaption>
        <div class="date">{{ fields['field_date'].content }}</div>
        <div class="lieu">{{ fields['field_lieu'].content }}</div>
    </figcaption>
</figure>
{{ drupal_block('comment_block') }}

Ich verwende das Modul Twig Tweak , um einen benutzerdefinierten Block in dieser Vorlage zu rendern. Dieser Block sollte alle Kommentare für das Bild laden. Dazu muss ich das nid des Knotens an meinen Block übergeben.

Hier ist der Code des Blocks:

CommentBlock.php

/**
 * Provides a 'CommentBlock' block.
 *
 * @Block(
 *  id = "comment_block",
 *  admin_label = @Translation("Comment block"),
 *  context = {
 *    "node" = @ContextDefinition("entity:node", label = @Translation("Node"))
 *  }
 * )
 */
class CommentBlock extends BlockBase implements ContainerFactoryPluginInterface {

  /**
   * Drupal\Core\Entity\EntityTypeManagerInterface definition.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * Constructs a new CommentBlock object.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param string $plugin_definition
   *   The plugin implementation definition.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->entityTypeManager = $entity_type_manager;
  }

  /**
   * {@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')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function build() {

    $build = [];

    $node = $this->getContextValue('node');
    kint($node->id());

    $build['#theme'] = 'comment_ajax';

    return $build;
  }

}

Ich versuche, den Kontext der Ansichtszeile in meinen Block zu bekommen. Aber ich bekomme diesen Fehler:

Drupal\Component\Plugin\Exception\ContextException : Required contexts without a value: node

Was mache ich falsch?

Ich kann meinen Block von template_preprocess_views_view_fields() laden, um ihn mit nid zu verknüpfen, aber ich versuche, die Kontextanmerkung zu verstehen.


Aktualisieren

Hier ist ein Bild der Ansicht. Mein benutzerdefinierter Block gibt nur den Linknamen "Kommentar" zurück.

(enter image description here

Ich lade jetzt den Block programmgesteuert, anstatt drupal_block Im Vorprozess zu verwenden.

$block             = \Drupal\block\Entity\Block::load('commentblock');
$variables['test'] = \Drupal::entityTypeManager()
  ->getViewBuilder('block')
  ->view($block);

Dann drucke ich diesen Block in views-view-fields.html.twig :

{{ fields['title'].content }}
{{ test }}

Wenn ich den Kontext in meinem Block kint, erhalte ich immer noch eine Fehlermeldung, außer wenn ich die Annotation required = FALSE Setze.

 *   context = {
 *     "node" = @ContextDefinition(
 *       "entity:node",
 *       label = @Translation("Current Node"),
 *       required = FALSE,
 *     )
 *   }

Der Kontext ist jedoch noch leer.

4
Kevin

Wenn Sie den Block platzieren, müssen Sie auswählen, wo der Block den Knotenwert erhalten soll.

Wählen Sie einen Knotenwert

(enter image description here

Knoten von URL

(enter image description here


Ah! Ich habe mein eigenes gefunden Problem bei DO . Möglicherweise müssen Sie den Kontext auch wie folgt abrufen:

 *   context = {
 *     "node" = @ContextDefinition(
 *       "entity:node",
 *       label = @Translation("Current Node"),
 *       required = FALSE,
 *     )
 *   }
4
leymannx

Nach vielen Versuchen habe ich mit dem Kontext-Plugin keine eigenständige Lösung für meinen Block gefunden. Aber ich habe einen Weg mit einer Vorverarbeitungsfunktion gefunden.

So erhalte ich das nid aus meiner Ansichtszeile:

function comment_ajax_preprocess_views_view_fields(&$variables) {

  $block_manager = \Drupal::service('plugin.manager.block');
  $config        = ['nid' => $variables['row']->nid];
  $plugin_block  = $block_manager->createInstance('comment_block', $config);

  $variables['blockComment'] = $plugin_block->build();
}

In dieser Vorverarbeitungsfunktion erhalte ich die Zeile nid und verwende sie in der Blockkonfiguration.

Und in meinem benutzerdefinierten Block:

public function build() {

  $build = [];

  $blockConfig     = $this->getConfiguration();
  $build['#theme'] = 'comment_ajax';
  $build['#nid']   = $blockConfig['nid'];

  return $build;
}

Ich bekomme das nid aus der Blockkonfiguration zurück.

Das funktioniert, aber ich suchte nach einem Weg ohne Vorverarbeitung, nur mit dem Kontext.

Ich suche immer noch nach einem besseren Weg :)

2
Kevin

Block-Plugins, die von BlockBase erben, können ihre Kontextwerte direkt über ContextAwarePluginBase::setContextValue($key, $value) festlegen. Diese Methode kann von einer Vorverarbeitungsfunktion verwendet werden, um Kontext einzufügen, der sonst nicht über die Route oder Umgebung verfügbar ist.

In meinem Fall habe ich einen Block, der in seinem Kontext eine Entität group benötigt:

<?php

namespace Drupal\middlebury_course_hub\Plugin\Block;

use Drupal\Core\Access\AccessResult;
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Session\AccountInterface;

/**
 * Provides a block with a link to the section's roster.
 *
 * @Block(
 *   id = "course_hub_roster_link",
 *   admin_label = @Translation("Roster Link"),
 *   category = @Translation("Course Hub"),
 *   context = {
 *     "group" = @ContextDefinition(
 *       "entity:group",
 *       label = @Translation("Current Group"),
 *       required = FALSE
 *     )
 *   }
 * )
 */
class RosterLinkBlock extends BlockBase {

  /**
   * {@inheritdoc}
   */
  protected function blockAccess(AccountInterface $account) {
    /** @var \Drupal\group\Entity\GroupInterface $group */
    if (($group = $this->getContextValue('group')) && $group->id()) {
      if ($group->hasPermission('view group_membership content', $account)) {
        return AccessResult::allowed();
      }
    }
    return AccessResult::forbidden();
  }

  /**
   * {@inheritdoc}
   */
  public function build() {
    // This block varies per group.
    $build['#cache']['contexts'] = ['group'];
    $build['#theme'] = 'course_hub_roster_link';
    /** @var \Drupal\group\Entity\GroupInterface $group */
    if (($group = $this->getContextValue('group')) && $group->id()) {
      $build['#group'] = $group;
    }

    // If no group was found, cache the empty result on the route.
    return $build;
  }

}

Ich wollte diesen Block für jede Gruppenentität anzeigen, die eine Zeile eines Ansichtsergebnisses war. Durch Hinzufügen einer Vorverarbeitungsfunktion zu meinem Modul konnte ich den Kontext group einfügen:

/**
 * Implements hook_preprocess_hook().
 */
function middlebury_course_hub_preprocess_group(&$variables) {
  if ($variables['view_mode'] == 'dashboard_item') {
    // Add the roster-link block to the build-array.
    $block = \Drupal::service('plugin.manager.block')
               ->createInstance('course_hub_roster_link');
    $block->setContextValue('group', $variables['group']);
    if ($block->access(\Drupal::currentUser())) {
      $variables['content']['roster_link'] = $block->build();
      $variables['content']['roster_link']['#weight'] = 2;
    }
  }
}

Dieselbe Technik sollte auch für Knoten funktionieren, die $block->setContextValue('node', $node); in Ihrer Funktion hook_preprocess_node Verwenden.

0
Adam Franco