1

What ist the correct way to load a View via Ajax and not breaking the view ajax functionality like the pager?

I tried it this way:

In a template:

<a href="/example-module/15?token=ugi2XH02Cumb3lsbSrOutwzRYSMXmn_bRKJI3FQ-hhk" class="btn use-ajax" role="button" rel="nofollow">
  {{- 'Load View' -}}
</a>

In the routing file:

example_module.example:
  path: '/example-module/{node_entity}'
defaults:
  _controller: '\Drupal\example_module\Controller\LoadViewController::render'
  _title: 'Load View'
options:
  parameters:
    node_entity:
      type: entity:node
requirements:
  _permission: 'access content'
  _csrf_token: 'TRUE'

In the Controller:

public function render(NodeInterface $node_entity, Request $request) {
  $node_id = $node_entity->id();
  if ($request->get(MainContentViewSubscriber::WRAPPER_FORMAT) == 'drupal_ajax') {
    $views_block = views_embed_view('load_view', 'block_1', $node_id);

    $response = new AjaxResponse();
    $selector = '#example-id';
    $replace = new ReplaceCommand($selector, \Drupal::service('renderer')->render($views_block));
    $response->addCommand($replace);
    return $response;
  }
  else {
    // For entities that don't have a canonical URL (like paragraphs),
    // redirect to the front page.
    $front = Url::fromUri('internal:/');
    $response = new RedirectResponse($front);
  }
  return $response;
}

This code works well. With two exceptions:

  • The view is not working with ajax (e.g. Pager). But the option "use AJAX" is checked in the UI --- I also tried it with the Views::getView() method and add explicit the $view->setAjaxEnabled(TRUE) option. No success.
  • The Pager of the View has the URL of the controller in it, not the URL from the current rendered page.

So if you click on the Pager of the new loaded Views, the page reloads and show you on a white screen the Ajax command, but no specific error, not in the console and not in the logs.

Is this way not working or what I'm doing wrong?

  • Views Ajax uses its own endpoint. It's hard to mix custom Ajax with Views Ajax. I would choose one of them. If you go with Views Ajax then deliver a basic version of the View and hide it in js until the user clicks a button. If you go with your custom Ajax then disable the Views Ajax and handle the incoming pager request in the controller. In this case you have to add use-ajax to the pager links as well, so that the returned ajax response is handled by the client. – 4k4 Oct 21 at 7:59
  • Thank you very much 4k4. The first option is not a good one in my situation, because that would mean that I have to load multiple views on the same page and maybe don't need them if the User don't click at the Load-Button. The second option is better in this context (perfomance), but that can mean a lot of work if you wanna go a step further and use exposed filter in the loaded view etc. So therefore option one is still the better one... And there is no other solution, maybe an option three? – handkerchief Oct 21 at 9:52
  • OK, I think it's clear what you are asking and we'll see if someone can provide an answer. By the way, I don't think there is a performance issue with the first option, because the initially rendered Views are cached the same way as any other rendered output. – 4k4 Oct 21 at 12:36
  • Another idea, is it possible to load the Block of the View and passing some arguments to the View instead load the View directly? Would that change anything? – handkerchief Oct 21 at 14:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.