Come posso rendere programmaticamente il campo di un nodo rispettando le impostazioni della modalità di visualizzazione?


9

Voglio rendere il campo di un nodo all'interno di un blocco. Funziona così:

<?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;

Ma questo non è al 100% come se volessi semplicemente rendere il campo normalmente, rendendolo visibile nelle impostazioni della modalità di visualizzazione.

Risposte:


0

Penso che la modalità di visualizzazione debba essere applicata al nodo, non al campo. Quindi è necessario ottenere il viewbuilder e rendere il nodo. Successivamente è possibile selezionare l'array di rendering per il campo dall'array di rendering del nodo. Un po 'così:

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

PS È necessario "[EntityTypeManager]" iniettato comunque come servizio @ entity_type.manager. Oppure scaricalo nel tuo plug-in di blocco create () da $ container-> get ('entity_type.manager').


1
non proprio. $nodeviewha #nodecome chiave
Alex

1
inoltre, questo rende il nodo, non campi separati
Alex

1
Sì, eseguo il rendering del nodo (e di tutti i suoi campi). Questo è ciò che modifichi nelle impostazioni della modalità di visualizzazione. Forse ho sbagliato la tua domanda.
Rainer Feike,

1
"$ nodeview [youfield-qui];" è nullo, almeno su Drupal 8.6.x
Onkeltem

1
Sostituisci "yourfield-here" con il nome della macchina del tuo campo.
Rainer Feike,

28

Per eseguire il rendering di un singolo campo con l'impostazione di visualizzazione di una modalità di visualizzazione è possibile utilizzare il view()metodo del campo:

Esempio per il rendering dell'immagine in formato teaser:

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

O il corpo in pieno:

$build['body'] = $node->body->view('full');

1
sfortunatamente, questo non rispetta le impostazioni della modalità di visualizzazione, come le impostazioni di etichette e formattatore
Alex,

1
Questo dovrebbe funzionare, puoi anche usare il debug del ramoscello con questo comando. Se si fornisce una modalità di visualizzazione esistente come stringa, il campo verrà formattato con questo. Se si fornisce una matrice è possibile dare le proprie impostazioni di visualizzazione, per esempio['label' => 'inline' ]
4K4

1
credo di averlo già provato ma non ha funzionato. proverò ancora. grazie finora
Alex,

1
Trovo che rispetti il ​​formatter, ma non le impostazioni del formatter. L'output di questo include le impostazioni corrette.
Grayside

1
questo essenzialmente mi ha portato alla risposta, dove posso ottenere la mia variabile in .twig: $vars['var_name'] = $node_object->field_name->view()[0]; e poi in un ramoscello, posso renderizzare {{var_name}}
bdanin,

4

Questa risposta si basa su https://drupal.stackexchange.com/a/208061/394

// 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);

Per rendere completamente programmatico il campo che finisci chiamando renderRoot(), il che stabilisce un contesto di rendering separato da quello che le risposte tipiche della pagina utilizzerebbero - un singolo contesto di rendering per una richiesta o una sotto-richiesta. Potremmo anche usare renderPlain(), ma poi sfuggirebbe a tutto.

Nel Drush repl ma non nella normale esecuzione della pagina, questo mi ha lanciato un avvertimento:

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

2

in relazione alla risposta di Alex , ecco come l'ho modificato per usare config_pages e creare un blocco global_footer:

<?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;

}

Probabilmente è meglio eseguire il rendering di campi arbitrari da un'impostazione di config_pages anziché estrarre dati da un nodo, ma immagino che dipenda davvero dal caso d'uso specifico su quale metodo sia il migliore.


2

Grazie alla risposta di Rainer Feike sono arrivato alla soluzione:

<?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;

}

Usando $viewBuilder->viewFieldposso rendere tutti i campi separatamente ho bisogno. Devo solo scoprire come aggiungere la memorizzazione nella cache in base alle impostazioni della modalità di visualizzazione, ma questa è un'altra domanda :)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.