Problem/Motivation
When a view is embedded through a Views Reference field and AJAX is enabled, the Views Reference settings are applied to attachment displays on AJAX requests, but not on the initial page load. Attachments therefore look and behave differently after the first AJAX refresh (e.g. after submitting an exposed filter).
The cause is in viewsreference_views_pre_view(). Attachments are rendered by their own cloned view executable:
- Initial page load: the settings live in
$view->element['#viewsreference']of the referenced display only. The attachment's executable has no such element, so the hook returns early and the attachment keeps its own configuration. - AJAX request: the settings are passed as
viewsreferencequery parameter. The hook reads them from the request for every view executable in that request, including the attachment's, and runs all enabled settings plugins against it.
viewsreference_views_pre_render() already guards against attachments with empty($view->is_attachment), but that check cannot simply be reused in hook_views_pre_view(): Views sets is_attachment on the parent executable while attaching, not on the attachment's own executable.
We noticed this with a settings plugin that overrides the style options of the referenced display: after an AJAX refresh, a responsive grid attachment lost its own style options and fell back to the plugin defaults. Since all enabled settings plugins run through the same code path, the built-in plugins (e.g. limit, offset, pager) are applied to attachments in the same way.
Steps to reproduce
- Create a view with a block display, enable AJAX and add an exposed filter.
- Add an attachment display attached to the block display, with "Inherit exposed filters" enabled and its own settings that differ from the block display (e.g. a different number of items or a different style).
- Embed the block display through a Views Reference field and enable a settings plugin that alters the view, e.g. "Limit", with a value different from the attachment's own setting.
- Load the page: the attachment uses its own configuration.
- Submit the exposed filter: after the AJAX refresh, the Views Reference settings are also applied to the attachment.
Expected: the attachment renders the same way before and after the AJAX refresh.
Actual: after the AJAX refresh, the Views Reference settings intended for the referenced display are also applied to the attachment.
Proposed resolution
Skip attachment displays in viewsreference_views_pre_view(), so AJAX requests behave like the initial page load:
// Attachments run in their own view executable. On normal page loads they
// never receive the settings, but on AJAX requests they would pick them up
// from the request and get e.g. the parent's style options applied. Skip
// them so AJAX and non-AJAX rendering behave the same.
if ($view->display_handler?->getPluginId() === 'attachment') {
return;
}
Attachments that should share settings with their parent can still do so through the existing "Inherit contextual filters/exposed filters/pager" options of the attachment display.
Remaining tasks
- Review the patch.
- Add a functional test covering an AJAX view with an attachment embedded via Views Reference.
User interface changes
None.
API changes
None. Settings plugins are no longer invoked for attachment displays during AJAX requests, matching the existing behaviour on initial page loads.
Data model changes
None.
| Comment | File | Size | Author |
|---|---|---|---|
| viewsreference-skip-attachments.patch | 785 bytes | schubie |
Issue fork viewsreference-3629365
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
Comment #3
schubie commentedComment #7
lmoeniI recently came across this problem in my projects.
The patch works as intended, but in my opinion the users would expect the attachment to be limited like the block it's attached to. Especially when "Inherit pager" is activated.
If that behavior is not wanted, the "Inherit pager" option on the attachment could be deactivated so that the limit only applies to the block.
That's why I created a new merge request where the limit gets applied to the attachment as well. I adjusted the test as well.