Views exposed form action incorrect for embedded views' displays with other displays with paths

Created on 19 January 2017, over 8 years ago
Updated 8 March 2023, about 2 years ago

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:

  1. Create a new view named "Ajax Test"
  2. Change the format to Table. In the settings make the title field sortable
  3. Edit the Title field to give it a label of "Title"
  4. 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.
  5. Under Advanced Options, enable AJAX for this view
  6. 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.
  7. 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
  8. 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.

  1. Install and enable the Page Example module to create a sample page we can embed into.
  2. Open 'Drupal\page_example\Controller\PageExampleController'
  3. 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.

🐛 Bug report
Status

Needs work

Version

10.1

Component
Views 

Last updated about 5 hours ago

Created by

🇺🇸United States hyperlinked San Jose, CA

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

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇺🇸United States alison

    I found this issue right after submitting a new one, darn.
    🐛 On views with AJAX enabled, exposed filter "reset" causes page load Active

    I'm not closing my new one quite yet, though, for a few reasons (in no particular order):

    1. I think the fact that the reset button causes a page load when AJAX is enabled is the root cause of the issue -- I think even on a view page display, hitting Reset shouldn't cause a page load, right?
    2. When I reproduce the issue, the form action is the view page display URL from the start, not just after I submit filters.
    3. I think my steps to reproduce are simpler? (but if folks agree and if the issue I created is closed as a duplicate, I could easily copy those steps to reproduce into here).
  • Open in Jenkins → Open on Drupal.org →
    Environment: PHP 8.1 & MySQL 5.6
    last update almost 2 years ago
    Build Successful
  • Open in Jenkins → Open on Drupal.org →
    Environment: PHP 8.1 & MySQL 5.7
    last update almost 2 years ago
    Composer error. Unable to continue.
  • 🇨🇦Canada Liam Morland Ontario, CA 🇨🇦

    As noted in #23, the problem seems to be that ::getLinkDisplay() chooses the first display that has a path. Why would it ever make sense to do this? This will often give the path of a different display and I don't see how that would ever be correct.

    This was fixed in views_block_filter_block by removing the loop that searches other displays; see #2979690: Incorrect form action URL for views that have page displays .

  • 🇩🇪Germany Anybody Porta Westfalica
  • 🇮🇪Ireland marksmith

    This is still an issue in Drupal 11.1 and it can become quite annoying for blocks with exposed filters (I use page reload, arguments, query parameters, and contextual filters in my block, no AJAX).

    When the first views display item with path (page, rss, etc.) in the current view is a view with a dynamic route (like node/%node/somepage), this also leads to a routing error, like this one: Symfony\Component\Routing\Exception\MissingMandatoryParametersException: Some mandatory parameters are missing ("node") to generate a URL for route "view.viewname.page_1". in Drupal\Core\Routing\UrlGenerator->doGenerate() (line 180 of /var/www/html/mysite/web/core/lib/Drupal/Core/Routing/UrlGenerator.php).

    The root cause of the issue was described by #23 (for Drupal 9) and reinforced in #38, and a workaround was suggested in #30.

    One small addition though that might help others. By default it's the first path within the current view which is chosen by the block. However, in the Pager > Link display section you can choose other displays with a path from the current (!) view as well. Only the "None" and "Custom URL" options of the Link display are not respected. (And ultimately the default None option is not respected by getLinkDisplay). So I created a random page (with the /node path), disabled it, and use this as a reference link for the block with the exposed filters.

  • 🇦🇺Australia acbramley

    This is probably a duplicate of 🐛 Problem with action path for embedded forms Needs work - there's a WIP MR up over there but as per comment 75 BC is going to be tricky for this fix.

  • First commit to issue fork.
Production build 0.71.5 2024