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