Drupal 8 / 9 / 10 : Programmatically render a view with contextual and exposed filters input
Par Mathieu le dimanche 10 mars 2024, 19:45 - Informatique - Lien permanent
Exposed Input and Contextual Input are two different ways of providing input to Drupal Views.
Contextual filters work with an ordered list of parameters, while Exposed Input works with a form that has a couple name/value for every input parameter.
Contextual Filters
The right way to render a view result with contextual filters is to generate a render array:
$render_array = [ '#type' => 'view', '#name' => 'YOUR_VIEW_NAME', '#display_id' => 'YOUR_VIEW_DISPLAY', '#arguments' => [CONTEXTUAL_FILTER_1, CONTEXTUAL_FILTER_2, ...], ];
You can then send the render array to a Twig variable, or render it programatically:
$result = \Drupal::service('renderer')->render($render_array); return $result->__toString();
We are using the __toString()
function to get the rendered HTML because the result returned by Drupal Render service is an object containing cache metadata.
Exposed Filters
The right way to render a view result with exposed filters is to generate a render array, and set the '#view#'
parameter with a view object where you can initialize the filters:
$view = \Drupal\views\Views::getView('YOUR_VIEW_NAME'); $view->setExposedInput([ 'YOUR_FILTER_NAME' => 'YOUR_FILTER_VALUE', ]); $render_array = [ '#type' => 'view', '#name' => 'YOUR_VIEW_NAME', '#view' => $view, '#display_id' => 'YOUR_VIEW_DISPLAY', '#arguments' => [CONTEXTUAL_FILTER_1, CONTEXTUAL_FILTER_2, ...], ];
You can then send the render array to a Twig variable, or render it programatically:
$result = \Drupal::service('renderer')->render($render_array); return $result->__toString();
We are using the __toString()
function to get the rendered HTML because the result returned by Drupal Render service is an object containing cache metadata.
Leaked Metadata and Early Rendering
If you render a view while rendering a controller output that is suppose to provide its own cache metadata (CacheableJsonResponse
for instance), and run on the error:
LogicException: The controller result claims to be providing relevant cache metadata, but leaked metadata was detected. Please ensure you are not rendering content too early.
Just wrap the rendering in a render context:
$context = new Drupal\Core\Render\RenderContext\RenderContext(); $html = \Drupal::service('renderer')->executeInRenderContext($context, function () { $render_array = [ '#type' => 'view', '#name' => 'YOUR_VIEW_NAME', '#display_id' => 'YOUR_VIEW_DISPLAY', '#arguments' => [CONTEXTUAL_FILTER_1, CONTEXTUAL_FILTER_2, ...], ]; $result = \Drupal::service('renderer')->render($render_array); return $result->__toString(); });