ViewsExposedForm has incorrect form submit URL if loaded through ajax

Created on 24 October 2023, about 1 year ago
Updated 12 December 2023, about 1 year ago

Problem/Motivation

Created as a separate issue from πŸ› Viewsform has incorrect form submit url if loaded through ajax Needs work .

It's not just broken for Viewsform, but also for ViewsExposedForm.

See πŸ› Submit broken when used with AJAX. Closed: works as designed

Steps to reproduce

If I have a view with exposed filters that has a Data Export view display and a Block view display, then even if the Block display is alone on a page by itself, without the Data Export attached to it, the Apply button will still incorrectly have the URL to the data export.

When using xDebug, I stepped through the code in ViewsExposedForm.

It has:

    if ($view->hasUrl()) {
      try {
        $form_action = $view->getUrl()->toString();
      }
      catch (InvalidParameterException $e) {
        $form_action = NULL;
      }
    }

The view does have a URL, and it returns the URL for the wrong display here, returning the Data Export URL if it has one. That happens because of this code in DisplayPluginBase:

  public function getRoutedDisplay() {
    // If this display has a route, return this display.
    if ($this instanceof DisplayRouterInterface) {
      return $this;
    }

    // If the display does not have a route (e.g. a block display), get the
    // route for the linked display.
    $display_id = $this->getLinkDisplay();
    if ($display_id && $this->view->displayHandlers->has($display_id) && is_object($this->view->displayHandlers->get($display_id))) {
      return $this->view->displayHandlers->get($display_id)->getRoutedDisplay();
    }

    // No routed display exists, so return NULL
    return NULL;
  }

and getLinkDisplay()...

  public function getLinkDisplay() {
    $display_id = $this->getOption('link_display');
    // If unknown, pick the first one.
    if (empty($display_id) || !$this->view->displayHandlers->has($display_id)) {
      foreach ($this->view->displayHandlers as $display_id => $display) {
        if (!empty($display) && $display->hasPath()) {
          return $display_id;
        }
      }
    }
    else {
      return $display_id;
    }
    // Fall-through returns NULL.
  }

So despite the fact that the block is on a page with its own route, it uses the Data Export URL, which is wrong.

The views code should not assume that the first link it finds on a display will be valid for a display without a link.

Workaround

I expect that adding a Page display with the correct URL and putting it right after the displays without links would make the views form have the correct URL on the form action.

You can also set the "Link Display" of the block display to a Custom URL (it's weirdly in the Pager part of the configuration) which would fix this issue.

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

✨ Feature request
Status

Active

Version

11.0 πŸ”₯

Component
ViewsΒ  β†’

Last updated about 5 hours ago

Created by

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @solideogloria
  • πŸ‡³πŸ‡±Netherlands Lendude Amsterdam

    This is by design. As you indicate, there are workarounds for this, but changing it would be a feature request, just not sure what that feature would be.
    Something like an option to add a setting for 'Use current URL' for blocks?

Production build 0.71.5 2024