Ideal way to ajax load a view in Drupal 8 with contextual filters

Viewed 876

I have a taxonomy called category.

I have a menu with links to each of these taxonomy items.

The Taxonomy page for each of these items has that menu and also contains a view which uses a contextual filter from the URL to filter the content of the view to content with that taxonomy term.

I wanted to Ajax load the view content when one of these menu items is clicked.

I've been able to achieve the desired result by enabling ajax on the view and using the following JavaScript.

(function ($) {
  Drupal.behaviors.course_browser = {
    attach: function (context, settings) {
      // should only be one menu, but guard against 0, and avoid the if statement.
      context.querySelectorAll(".menu--categories").forEach((menu) => {
        // for each link in the menu
        menu.querySelectorAll(".nav-link").forEach((link) => {
          // on click
          link.addEventListener("click", (event) => {
            event.preventDefault();

            // fetch the taxonomy term id from menu link
            let tid = event.target.dataset.drupalLinkSystemPath.replace(
              "taxonomy/term/",
              ""
            );

            // make the ajax call
            $.ajax({
              url: "/views/ajax",
              type: "post",
              data: {
                view_name: "course_browser",
                view_display_id: "block_1",
                view_args: tid,
              },
              success: (response) => {
                response.forEach((action) => {
                  // the response contains a number of commands; I'm not sure
                  if (
                    action.command === "insert" &&
                    action.method === "replaceWith"
                  ) {
                    let viewElement = document.querySelector(VIEW_SELECTOR);

                    // update the html of the course browser
                    viewElement.innerHTML = action.data;

                    // update the url in the browser
                    window.history.pushState("", "", event.target.href);

                    // seperate function to adjust my page title
                    updatePageTitle(event.target.textContent);

                    // call drupal behaviours passing context to ensure all the other js code gets a chance to manipulate the new content
                    Drupal.attachBehaviors(viewElement);
                  }
                });
              },
              error: function (data) {
                console("An error occured fetching the course browser");
              },
            });
          });
        });
      });
    },
  };
})(jQuery);

I'm looking for feedback on my approach here; my main concern at the moment is the way I handle the response. When I look at the response I receive something like that shown below:

0: {command: "settings", settings: {…}, merge: true}
1: {command: "add_css", data: "<link rel="stylesheet" media="all" href="/core/modules/views/css/views.module.css?qcog4i" />↵"}
2: {command: "insert", method: "append", selector: "body", data: "<script src="/core/assets/vendor/jquery/jquery.min…/js/modules/views/ajax_view.js?qcog4i"></script>↵", settings: null}
3: {command: "insert", method: "replaceWith", selector: ".js-view-dom-id-", data: "The HTML"}

As you can see, I'm manually handling the response by cherry picking the part I want and replacing the HTML of view. Based on what I've seen around Drupal, I think there should be something I can pass this response to that handles it automatically. When I look at the window object of the browser, I can see Drupal.AjaxCommands which looks like it was designed to handle this, but I'm not sure how I should be using this.

I also note that in the case I can simply pass this response to something to have those AjaxCommands executed, the selector ".js-view-dom-id-" isn't right. So I could tweak the response before I pass it, or if someone knows a way to adjust the ajax request to perhaps get the right selector, that would be ideal.

Sorry if this info is readily available somewhere...there are quiet a few resources around related to Drupal and Ajax but I haven't been able to find examples of exactly what I'm doing here, the circumstances always seem to differ enough that I can't use them.

Thanks for any help.

0 Answers
Related