Wie kann ich das Feld eines Knotens programmgesteuert unter Berücksichtigung der Einstellungen für den Ansichtsmodus rendern?

9

Ich möchte das Feld eines Knotens innerhalb eines Blocks rendern. Es funktioniert so:

<?php

if ($node) {
  if (isset($node->field_body_secondary) && $field = $node->field_body_secondary->value) {
    $markup = render($field);
    $build = array(
      '#type' => 'markup',
      '#markup' => $markup,
    );
  }
}

return $build;

Dies ist jedoch nicht 100% ig, als würde ich das Feld nur normal rendern und es in den Einstellungen des Ansichtsmodus sichtbar machen.

Alex
quelle

Antworten:

0

Ich denke, der Ansichtsmodus sollte auf den Knoten angewendet werden, nicht auf das Feld. Sie müssen also den Viewbuilder herunterladen und den Knoten rendern. Anschließend können Sie das gerenderte Array für das Feld aus dem Render-Array des Knotens auswählen. Ein bisschen wie das:

$vb = [EntityTypeManager]->getViewBuilder('node'); // Drupal\node\NodeViewBuilder
$nodeview = $vb->view($node, $viewmode);
$fieldrenderarray = $nodeview[youfield-here];

PS Sie müssen sowieso "[EntityTypeManager]" als @ entity_type.manager-Dienst einfügen. Oder holen Sie es sich in Ihrem Block-Plugin create () von $ container-> get ('entity_type.manager').

Rainer Feike
quelle
1
nicht ganz. $nodeviewhat #nodeals Schlüssel
Alex
1
Dies rendert auch den Knoten, nicht separate Felder
Alex
1
Ja, ich rendere den Knoten (und alle seine Felder). Dies ist jedoch das, was Sie in Ihren Ansichtsmoduseinstellungen anpassen. Vielleicht habe ich deine Frage falsch verstanden.
Rainer Feike
1
"$ nodeview [youfield-here];" ist null, zumindest auf Drupal 8.6.x
Onkeltem
1
Ersetzen Sie "yourfield-here" durch den Maschinennamen Ihres Feldes.
Rainer Feike
28

Um ein einzelnes Feld mit der Anzeigeeinstellung eines Ansichtsmodus zu rendern, können Sie die view()Methode des Felds verwenden:

Beispiel für das Rendern des Bildes im Teaser-Format:

$build['image'] = $node->field_image->view('teaser');

Oder der Körper in vollem Umfang:

$build['body'] = $node->body->view('full');
4k4
quelle
1
Leider werden die Einstellungen für den Ansichtsmodus wie Beschriftungen und Formatierer nicht berücksichtigt
Alex
1
Dies sollte funktionieren, Sie können sogar Twig Debug mit diesem Befehl verwenden. Wenn Sie einen vorhandenen Ansichtsmodus als Zeichenfolge angeben, wird das Feld damit formatiert. Wenn Sie ein Array bereitstellen, können Sie Ihre eigenen Anzeigeeinstellungen ['label' => 'inline' ]
angeben
1
Ich glaube, ich habe das schon versucht, aber es hat nicht funktioniert. Ich werde es nochmal versuchen. bisher danke
Alex
1
Ich finde, es respektiert den Formatierer, aber nicht die Formatierereinstellungen. Die Ausgabe enthält die richtigen Einstellungen.
Grayside
1
Dies brachte mich im Wesentlichen zu der Antwort, wo ich meine Variable in .twig erhalten kann: $vars['var_name'] = $node_object->field_name->view()[0]; und dann in Zweig kann ich {{var_name}}
bdanin
4

Diese Antwort baut auf /drupal//a/208061/394 auf

// Designate the field we want to render.
$field_name = 'body';
// Retrieve a render array for that field with the given view mode.
$render_array = $entity->$field_name->view('full');
// Render the result.
\Drupal::service('renderer')->renderRoot($render_array);

Um das Feld, das Sie durch Aufrufen beenden renderRoot(), vollständig programmgesteuert zu rendern , wird ein separater Renderkontext erstellt, der von den typischen Seitenantworten getrennt ist - ein einzelner Renderkontext für eine Anforderung oder Unteranforderung. Wir könnten es auch gebrauchen renderPlain(), aber dann würde es allen Dingen entkommen.

In der Drush-Antwort, aber nicht in der normalen Seitenausführung, warnte mich dies:

PHP warning:  DOMDocument::loadHTML(): Tag drupal-entity invalid in Entity, line: 1 in /drupal/core/lib/Drupal/Component/Utility/Html.php on line 286
Grayside
quelle
2

Im Zusammenhang mit Alex 'Antwort habe ich Folgendes geändert, um config_pages zu verwenden und einen global_footer-Block zu erstellen:

<?php

public function build() {
$config_name = 'global_footer';
$config = config_pages_config($config_name);
$build = array();
$markup = array();

$fieldsToRender = array(
  'field_body', 'field_foo', 'field_bar'
);

$viewmode = 'default';
$entityType = 'config_pages';
$display = entity_get_display($entityType, $config_name, $viewmode);
$viewBuilder = \Drupal::entityTypeManager()->getViewBuilder($entityType);

foreach ($fieldsToRender as $field_name) {
  if (isset($config->{$field_name}) && $field = $config->{$field_name}) {
    $fieldRenderable = $viewBuilder->viewField($field, $display->getComponent($field_name));
    if (count($fieldRenderable) &&! empty($fieldRenderable)) {
      $markup[] = \Drupal::service('renderer')->renderRoot($fieldRenderable);
    }
  }
}

if (count($markup)) {
  $build = array(
    '#type' => 'markup',
    '#markup' => implode("", $markup),
  );
}

return $build;

}

Es ist wahrscheinlich besser, beliebige Felder aus einem config_pages-Setup zu rendern, als Daten von einem Knoten abzurufen, aber ich denke, es hängt wirklich vom spezifischen Anwendungsfall ab, welche Methode die beste ist.

Bdanin
quelle
2

Dank der Antwort von Rainer Feike kam ich zu der Lösung:

<?php

public function build() {
  $node = \Drupal::routeMatch()->getParameter('node');
  $build = array();
  $markup = array();

  $fieldsToRender = array(
    'field_node_ref', 'field_foo', 'field_bar',
  );

  $viewmode = 'default';
  $entityType = 'node';
  $display = entity_get_display($entityType, $node->getType(), $viewmode);
  $viewBuilder = \Drupal::entityTypeManager()->getViewBuilder($entityType);

  foreach ($fieldsToRender as $field_name) {
    if (isset($node->{$field_name}) && $field = $node->{$field_name}) {
      $fieldRenderable = $viewBuilder->viewField($field, $display->getComponent($field_name));
      if (count($fieldRenderable) &&! empty($fieldRenderable)) {
        $markup[] = \Drupal::service('renderer')->renderRoot($fieldRenderable);
      }
    }  
  }

  if (count($markup)) {
    $build = array(
      '#type' => 'markup',
      '#markup' => implode("", $markup),
    );
  }

  return $build;

}

Mit $viewBuilder->viewFieldkann ich alle benötigten Felder separat rendern. Ich muss nur herausfinden, wie man Caching in Abhängigkeit von den Einstellungen des Ansichtsmodus hinzufügt, aber dies ist eine andere Frage :)

Alex
quelle