Problem/Motivation
When an embedded view display (such as a block) has exposed filters, if the view also contains a display with a path (page, export, etc) then the exposed form action will be set to the other display's path. This results in Reset buttons redirecting to other displays for example.
Proposed resolution
This is a tricky one, this could be as involved as rewriting the Drupal\views\Plugin\views\display\DisplayPluginBase::getLinkDisplay
logic.
Remaining tasks
Write a failing test
Find a solution
Original report
When a view is setup to use the "Embed" display in a view, using AJAX in the form in any way will cause the action attribute of the HTML form object to be rewritten to submit to '/views/ajax' instead of the current page. This issue is harmless unless the filter in your embedded view uses the Reset button to clear the form and reload the page. When the Reset button is pressed, it'll direct you to /views/ajax instead of your current page.
A variation of this bug is if you have both a Page display setup and an Embed display setup in the view. If both of these displays exist in the same view, then the form's action attribute for the filter in the Embed display will be rewritten to submit to whatever path you setup for the Page display. I'll use this more elaborate scenario in my steps below.
To reproduce this bug:
- Create a new view named "Ajax Test"
- Change the format to Table. In the settings make the title field sortable
- Edit the Title field to give it a label of "Title"
- Add the Title field to the Filter Criteria with the filter configured to use the Contains operator. Check the "Expose this filter to visitors" box.
- Under Advanced Options, enable AJAX for this view
- In the Exposed Form options, make sure Basic is chosen as the type and in the settings check off the box that inserts a Reset button.
- Add a "Page" display to this view. Keep all the same settings. Only edit the path for the Page display. Use "/wrong-endpoint" as the path
- Save the view
Now we need to embed this view into a page. I'm going to use the Page Example module from the Drupal Examples for Developers set of modules for the dummy page needed to create an embedded view display, but it can be embedded in other ways and would still work the same.
- Install and enable the Page Example module to create a sample page we can embed into.
- Open 'Drupal\page_example\Controller\PageExampleController'
- Edit the description method and append the following before the "return $build" line:
$build['test'] = views_embed_view('ajax_test', 'embed_1');
Go to the example page at '/examples/page-example'. Your embedded view should be there with the exposed filter. Inspect the HTML form object. The action attribute at this time should be '/examples/page-example'.
Now use the exposed filter to filter the table results. The results will narrow to match your search terms and the "Reset" button will appear. Inspect the form object again. The form will now submit to '/wrong-endpont'. The AJAX parts of the view will continue to work. You can use the table header sort. You can use new search terms and your results will filter as expected, but if you press the Reset button, you'll be redirected to the '/wrong-endpoint' page that was created as a Page type of display for this view.
Fixed by
π
Exposed filter reset redirects user to 404 page on AJAX view when placed as a block
Fixed
so it goes to the current page instead.
This issue does not occur if the view in question is not an embedded view. If you try to repeat this behavior on the Views Page that we created at /wrong-endpoint, you will get the correct behavior. The form's action attribute will not get changed to direct to the wrong page when AJAX rebuilds the form.