text: Q:
  
  AJAX Views with filter as path component
  
  I have a view of Commerce products of type Print. The product type Print has a reference on a Taxonomy called Category. I setup the Category field as an exposed filter (dropdown) for my View page. The View uses AJAX and the URL is /prints.
  If I want to load my View with a preselected category, I can go to http://d8.local/prints?category=1 which displays the View already filtered and with the corresponding category selected in the dropdown.
  I could setup a contextual filter and a relationship on the View and set the path to prints/% so that I could filter and access it as http://d8.local/prints/landscapes where landscapes is one of the vocabulary terms, which feels better than ?category=1.
  When I do so however, going to http://d8.local/prints/landscapes then using the exposed filter, it will filter the already filtered results. Also going to /landscapes doesn't select the option in the dropdown.
  Is there a way to combine the 2 functionalities?
  Edit:
  To summarize the functionalities I am after:
  
  I should be able to filter the products by category by adding the vocabulary term name as a path component, ie. /prints/landscapes.
  
  When accessing the View with the category as the path component, the appropriate category exposed filter dropdown option should be selected, ie. Landscapes should be selected in the dropdown if accessing /prints/landscapes.
  
  I should be able to filter the View using AJAX when manually selecting another category from the exposed filter dropdown.
  
  The main page title must be updated based on the category whichever way the view was loaded (page load and AJAX reload)
  
  Ideally, I would update the URL when manually selecting a category from the dropdown, but I suppose that's a separate question and it shouldn't be too hard to handle.
  
  A:
  
  I tried many different complicated approaches, before I found a much easier solution that suits my needs so I am posting this as a solution.
  I setup my prints View this way:
  
  Category is added as an exposed filter
  No contextual filter, no relationship
  Set the view path to prints/%
  Use AJAX: Yes
  
  I created a module and used hook_views_pre_build() to get the category from the url parts, ie. get landscapes from the path /prints/landscapes then load the vocabulary term by name and if the term exists, set the exposed filter to the term id.
  /**
   * Implements hook_views_pre_build().
   */
  function MYMODULE_views_pre_build(\Drupal\views\ViewExecutable $view) {
  
    $view_ids = ['prints'];
  
    if (isset($view) && in_array($view->id(), $view_ids)) {
  
      // Get exposed input
      $exposedInput = $view->getExposedInput();
  
      // If exposed input is not set
      if (empty($exposedInput['category'])) {
  
        // Get current path
        $current_path = \Drupal::service('path.current')->getPath();
        $uri_segments = explode('/', $current_path);
  
        // 2nd uri segment is the category (term name)
        $current_category = isset($uri_segments[2]) ? $uri_segments[2] : NULL;
  
        if ($current_category !== NULL) {
  
          // Set vocabulary id
          $vid = 'photo_category';
  
          // Load term by name from vocabulary
          $term = \Drupal::entityTypeManager()
            ->getStorage('taxonomy_term')
            ->loadByProperties(['vid' => $vid, 'name' => $current_category]);
  
          // If term was found
          if ($term) {
  
            // Get first array element
            $term = reset($term);
  
            // Filter view by setting exposed input to term id
            $view->setExposedInput(['category' => $term->id()]);
          }
        }
      }
    }
  }
  
  This fixes filtering the view on page load when the category is in the URL.
  As I also wanted to update the page title based on the selected category, I created an EventSubscriber for the AJAX response. All I do here is load the Category term name based on the exposed filter value, then use an HtmlCommand to update the page title.
  <?php
  
  namespace Drupal\MYMODULE\EventSubscriber;
  
  use Drupal\views\Ajax\ViewAjaxResponse;
  use Drupal\Core\Ajax\HtmlCommand;
  use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
  use Symfony\Component\HttpKernel\KernelEvents;
  use Drupal\taxonomy\Entity\Term;
  
  /**
   * Response subscriber to handle View AJAX responses.
   */
  class ViewAjaxResponseSubscriber implements EventSubscriberInterface {
  
    /**
     * Adds an AJAX command to ViewAjaxResponse.
     */
    public function onResponse(FilterResponseEvent $event) {
  
      $response = $event->getResponse();
  
      if ($response instanceof ViewAjaxResponse) {
  
        $view_ids = ['prints'];
        $view = $response->getView();
  
        if (isset($view) && in_array($view->id(), $view_ids)) {
  
          $titleSelector = '.page__header h1';
  
          if ($view->exposed_data['category'] !== 'All') {
  
            $term = Term::load($view->exposed_data['category']);
            $name = $term->getName();
  
            $title = 'Prints in category <em class="text-grey">' . $name . '</em>';
  
            $response->addCommand(new HtmlCommand($titleSelector, $title));
          } else {
  
            $response->addCommand(new HtmlCommand($titleSelector, 'Prints - All categories'));
          }
        }
      }
    }
  
    /**
     * {@inheritdoc}
     */
    public static function getSubscribedEvents() {
      $events[KernelEvents::RESPONSE][] = ['onResponse'];
      return $events;
    }
  
  }
  
  I'll do the same for when I load the view with the category in the URL, using hook_views_pre_render():
  /**
   * Implements hook_views_pre_render().
   */
  function MYMODULE_views_pre_render(\Drupal\views\ViewExecutable $view) {
  
    $view_ids = ['prints'];
  
    if (isset($view) && in_array($view->id(), $view_ids)) {
  
      if ($view->exposed_data['category'] !== 'All') {
  
        // Load category (term name) from View exposed filter data
        $term = Term::load($view->exposed_data['category']);
        $name = $term->getName();
  
        // Update View title with category (term name)
        $view->setTitle('Prints in category <em class="text-grey">' . $name . '</em>');
      }
    }
  }
  
  My last requirement was to update the URL when the view would be filtered with AJAX so in my module Javascript file:
  Drupal.behaviors.viewsAjax = {
  
      attach: function (context, settings) {
  
          // Attach action to Drupal Ajax Views event
          $(document).once('#views-exposed-form-prints-page-1', context).ajaxSuccess(function (event, data) {
  
              if ($('#views-exposed-form-prints-page-1').length) {
  
                  let stateUri = '/prints/' + $('#views-exposed-form-prints-page-1 select[name="category"] > option:selected').text().toLowerCase();
                  window.history.replaceState('', '', stateUri);
              }
          });
      }
  };
  
  