Problem/Motivation

The render method in plugins for full and mini pager (\Drupal\views\Plugin\views\pager\Full::render and \Drupal\views\Plugin\views\pager\Mini::render) both are setting the #route_name to either <current> or <none>. The former is used in live preview of views, the latter in all other cases.

Outside of the live preview, this results in hrefs for the page links that have an empty path, and only contain the options. This is working OK for all views with the page display because the request to another page will fall back to the current page by the browser.

But for views loaded by ajax, this causes an issue. Best example to reproduce this is the media library in CKEditor which opens in a modal dialog. The empty path in href leads to the problem that the ajax request goes to /node/456/edit?options instead of /media-library/?options.

Now, for a different reason, mini and full pager are behaving differently.

The mini pager, which is the default for media browser, uses \Drupal\views\Hook\ViewsThemeHooks::preprocessViewsMiniPager for pre-processing, and there the route is hard-coded to <current>, so that pre-processor doesn't care about the route name provided by the pager plugin.

On the other hand, the full pager uses the \Drupal\Core\Pager\PagerPreprocess::preprocessPager pre-processor and that uses the route name as provided by the plugins.

In summary, there are several issues at once. The pager plugins should also use <current> as the route name for ajax requests, and the mini pager preprocessor should replace the hard-coded route name by the provided variable. The former is a real issue, the latter is cosmetics.

Steps to reproduce

On any of main/11.x/11.3.x

  • composer require drupal/devel_generate
  • drush si standard -y
  • drush en media_library devel_generate -y
  • drush genmd --media-types=image
  • drush uli and log in
  • Edit any of the text formats using CKEditor
  • Add Media Library to the toolbar and enable the "Embed media" plugin and save
  • Configure pager on media library view to full
  • Add an article
  • Press Add media to open the media library
  • Navigate to page 2 or later
  • Observe modal display content of node/add/article form

Proposed resolution

Update the pager plugins to use the current route also for ajax requests, and update the mini pager pre-process to also use that route name instead of the hard-coded one.

Issue fork drupal-3567237

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

jurgenhaas created an issue. See original summary.

jurgenhaas’s picture

Issue summary: View changes

Turns out the mini pager pre-processor does not receive the route name argument from the plugin, that's why it needs to remain hard-coded. I've updated the original post accordingly.

jurgenhaas’s picture

Status: Active » Needs review

The MR fixes the issue with the media library, but I'm uncertain if that's the correct approach, therefore not writing any tests yet.

rkoller’s picture

one additional detail. after todays discussions, out of curiosity i've installed 11.2.0. With that version the problem is not reproducible.

and i've also checked out the MR and it is fixing the problem for me as well in a local test on 11.x.

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests

Thanks for reporting as always!

Think next step would be to address the phpstan issue and add test coverage.

jurgenhaas’s picture

@smustgrave I'm uncertain at this point if my suggested solution is the best approach. We may require some feedback from @catch and @berdir first, as the change got introduced when they migrated the preprocess_pager to OO hooks and they may have some different ideas on how that should be handled.

smustgrave’s picture

Issue summary: View changes

Added the remaining tasks section and that the approach needs to be agreed upon.

jurgenhaas’s picture

I've pinged contributors to the related issue in Slack asking for their review.

godotislate’s picture

StatusFileSize
new178.25 KB

I was not able to reproduce this issue against 11.3.2 or 11.x. Steps taken:

  • composer require drupal/devel_generate
  • drush si standard -y
  • drush en media_library devel_generate -y
  • drush genmd --media-types=image
  • drush uli and log in
  • Add an image media field to the Article content type
  • Configure pager on media library view to full
  • Add an article
  • Press Add media to open the media library
  • Navigate to page 2 or later
  • Observe media library contains media elements

Screenshot:Screenshot of media library widget on page 2

samit.310@gmail.com made their first commit to this issue’s fork.

jurgenhaas’s picture

Thanks @godotislate for testing this. I went through all your steps again and I can confirm that this is not an issue with the media field for some strange reason.

But it is in the CKEditor, although the links in the pager are identical, AFAIKT.

godotislate’s picture

@jurgenhaas thanks for the updated reproduction steps. I was able to see the same issue you did. I've updated the Steps to reproduce in the IS.

Doing a git bisect, I found #3122526: Pager links inside a modal do not open in the modal is the culprit. I confirmed that when testing against mainand reverting that issue's changes to core/lib/Drupal/Core/Pager/PagerPreprocess.php, the the pager for media library opened from CKEditor works correctly again.

Haven't investigated further to see whether the fix in the MR here is the best way forward.

smustgrave’s picture

Thanks for digging into this btw!

godotislate’s picture

Following up from #13, in the specific case of the media library being opened in a modal from CKEditor this issue is this:

  • Drupal\Core\Pager\PagerPreprocess::preprocessPager() is adding the 'use-ajax' class to all pager links, if the pager is being rendered in a modal
  • The media_library view uses AJAX by default
  • In ajax.js, Drupal.behaviors.AJAX calls Drupal.ajax.bindAjaxLinks, which AJAX-ifies all the use-ajax links in the document
  • In ajax_view.js, Drupal.views.ajaxView eventually calls Drupal.views.ajaxView.prototype.attachPagerLinkAjax on all the pager links in the view and AJAX-ifies those links, and when doing so, adds data about the view to be sent in the request when the pager link is clicked
  • Drupal.behaviors.AJAX runs before Drupal.views.ajaxView, so the AJAX click handler from Drupal.ajax.bindAjaxLinks runs instead of the handler from Drupal.views.ajaxView.prototype.attachPagerLinkAjax, so the request does not include the data associating the pager with the view, and so the node form is displayed in the modal instead of the media library view. (It also seems to have a side effect of removing the CKEditor toolbar from the editor as well.)

This can be verified by commenting out the 'class' => ['use-ajax'], in this stanza of Drupal\Core\Pager\PagerPreprocess::preprocessPager():

    if ($this->requestStack->getCurrentRequest()?->get(MainContentViewSubscriber::WRAPPER_FORMAT) === 'drupal_modal') {
      $link_attributes = [
        'class' => ['use-ajax'],
        'data-dialog-type' => 'modal',
        'data-accepts' => 'application/json',
      ];
    }

If that class is not applied to the pager links, the media library pager works correctly in the CKEditor modal.

I'm not sure what the best way is to address this specifically. Maybe some property like "#disable_modal_ajax_links" can be used in the preprocess to prevent use-ajax class from being added in modals, and the the render array returned from Drupal\views\Plugin\views\pager\Full::render() could set that to TRUE.

Setting the route to <none> might also be fine, but if the behavior ends up as expected, there are still two AJAX click handlers attached to every pager link.

Separately, the fix for #3122526: Pager links inside a modal do not open in the modal might have a separate bug in that the link attributes aren't applied to the "Last" pager link. Not sure whether that should be addressed here or in a new issue.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.

alorenc made their first commit to this issue’s fork.

alorenc’s picture

Added MediaLibraryWithPagerTest, which proves the issue described in #15. Provided a code suggestion involving an additional property, but I have some doubts about it.

godotislate’s picture

Provided a code suggestion involving an additional property, but I have some doubts about it.

@alorenc Thank you for your great work on this! I also have doubts, but there didn't seem to be another way to detect that a pager is a view pager and that Views will handle making them AJAX links.

I added some MR comments, but as I was reviewing, it occurred to me that a View that is not configured to use AJAX and is put in a modal will have use-ajax links that will probably not load the view correctly.

One way forward is maybe this:

  • Start with @jurgenhaas original approach by changing the route_name logic (Need to confirm that existing tests pass)
  • Change the selector in ajax_view.js:
      Drupal.views.ajaxView.prototype.attachPagerAjax = function () {
        this.$view
          .find(
            '.js-pager__items a, th.views-field a, .attachment .views-summary a',
          )
          .each(this.attachPagerLinkAjax.bind(this));
      };
    

    to '.js-pager__items a:not(.use-ajax), th.views-field a, .attachment .views-summary a',

  • Include the FJ MediaLibraryWithPagerTest in MR 14654. That's a very useful test

Anyone else have thoughts or suggestions?

godotislate’s picture

Separately, the fix for #3122526: Pager links inside a modal do not open in the modal might have a separate bug in that the link attributes aren't applied to the "Last" pager link. Not sure whether that should be addressed here or in a new issue.

Stubbed #3572047: "Last" pager links inside a modal do not open in the modal for this.

jurgenhaas changed the visibility of the branch 3567237-skip_modal_ajax to hidden.

jurgenhaas changed the visibility of the branch 3567237-mini-pager-and to hidden.

jurgenhaas’s picture

Status: Needs work » Reviewed & tested by the community
Issue tags: -Needs tests

I've tested MR!14654 successfully. Hidden the older MRs for that reason. Also removed the tag as a test is now available too.

sivaji_ganesh_jojodae made their first commit to this issue’s fork.

poker10’s picture

Status: Reviewed & tested by the community » Needs work

Thanks for working on this! There are still unresolved comments in the MR, so moving back to NW for these.

justcaldwell’s picture

Just here to concur with #25—this resolves the issue for us with ckeditor Media Library modals on 11.3.8. Thanks!