Comment puis-je restituer par programmation le champ d'un nœud en respectant les paramètres du mode d'affichage?

9

Je veux rendre le champ d'un nœud à l'intérieur d'un bloc. Cela fonctionne comme ceci:

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

Mais ce n'est pas 100% comme si je rendais simplement le champ normalement, le rendant visible dans les paramètres du mode d'affichage.

Alex
la source

Réponses:

0

Je pense que le viewmode devrait être appliqué au nœud, pas au champ. Vous devez donc obtenir le générateur de vues et rendre le nœud. Ensuite, vous pouvez choisir le tableau rendu pour le champ dans le tableau de rendu node'r. Un peu comme ça:

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

PS Vous devez "[EntityTypeManager]" injecté de toute façon en tant que service @ entity_type.manager. Ou récupérez-le dans votre Block-Plugin create () à partir de $ container-> get ('entity_type.manager').

Rainer Feike
la source
1
pas assez. $nodeviewa #nodepour clé
Alex
1
aussi, cela rend le noeud, pas les champs séparés
Alex
1
Oui, je rend le nœud (et tous ses champs). Mais c'est ce que vous ajustez dans vos paramètres de mode d'affichage. J'ai peut-être mal répondu à votre question.
Rainer Feike
1
"$ nodeview [youfield-here];" est nul, au moins sur Drupal 8.6.x
Onkeltem
1
Remplacez "votre champ ici" par le nom de la machine de votre champ.
Rainer Feike
28

Pour rendre un champ unique avec le paramètre d'affichage d'un mode d'affichage, vous pouvez utiliser la view()méthode du champ:

Exemple de rendu d'image au format teaser:

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

Ou le corps en entier:

$build['body'] = $node->body->view('full');
4k4
la source
1
malheureusement, cela ne respecte pas les paramètres du mode d'affichage, comme les étiquettes et les paramètres du formateur
Alex
1
Cela devrait fonctionner, vous pouvez même utiliser le débogage de brindille avec cette commande. Si vous fournissez un mode d'affichage existant sous forme de chaîne, le champ sera formaté avec cela. Si vous fournissez un tableau, vous pouvez donner vos propres paramètres d'affichage, par exemple['label' => 'inline' ]
4k4
1
Je crois que j'ai déjà essayé cela mais cela n'a pas fonctionné. Je vais réessayer. merci jusqu'à présent
Alex
1
Je trouve que cela respecte le formateur, mais pas les paramètres du formateur. La sortie de ceci inclut les paramètres corrects.
Grayside
1
cela m'a essentiellement amené à la réponse, où je peux obtenir ma variable en .twig: $vars['var_name'] = $node_object->field_name->view()[0]; puis en brindille, je peux rendre {{var_name}}
bdanin
4

Cette réponse s'appuie sur 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);

Pour rendre complètement par programmation le champ que vous terminez en appelant renderRoot(), ce qui établit un contexte de rendu distinct de celui que les réponses de page habituelles utiliseraient - un seul contexte de rendu pour une demande ou une sous-demande. Nous pourrions également utiliser renderPlain(), mais cela échapperait à tout.

Dans la réponse Drush mais pas dans l'exécution de page normale, cela m'a lancé un avertissement:

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
la source
2

en relation avec la réponse d' Alex , voici comment je l'ai modifié pour utiliser config_pages et construire un bloc 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;

}

Il est probablement préférable de rendre des champs arbitraires à partir d'une configuration config_pages plutôt que d'extraire des données d'un nœud, mais je suppose que cela dépend vraiment du cas d'utilisation spécifique quant à la meilleure méthode.

bdanin
la source
2

Grâce à la réponse de Rainer Feike, je suis parvenu à la solution:

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

}

En utilisant $viewBuilder->viewFieldJe peux rendre tous les champs dont j'ai besoin séparément. J'ai juste besoin de savoir comment ajouter la mise en cache en fonction des paramètres du mode d'affichage, mais c'est une autre question :)

Alex
la source