Problem/Motivation

When using the HTMX native hx-boost attribute on the <body> tag, HTMX does replace the page contents, but

I think this is a general problem that Drupal wraps the HTMX library to be an Ajax replacement in a too aggressive way. There are use cases outside of Drupal's Ajax system. For example, hx-boost is not something that Drupal Ajax would've been used for.

Steps to reproduce

  • Add hx-boost="true" attribute to the <body> tag, for example via template_preprocess_html.
  • See that HTMX itself does the job, but you see the unexpected effects as listed above.

Proposed resolution

Within htmx-assets.js, there is the following event listener:

  htmx.on('htmx:configRequest', ({ detail }) => {
    const url = new URL(detail.path, document.location.href);
    if (Drupal.url.isLocal(url.toString())) {
      // Allow Drupal to return new JavaScript and CSS files to load without
      // returning the ones already loaded.
      // @see \Drupal\Core\StackMiddleWare\AjaxPageState
      // @see \Drupal\Core\Theme\AjaxBasePageNegotiator
      // @see \Drupal\Core\Asset\LibraryDependencyResolverInterface::getMinimalRepresentativeSubset()
      // @see system_js_settings_alter()
      const pageState = drupalSettings.ajaxPageState;
      detail.parameters['ajax_page_state[theme]'] = pageState.theme;
      detail.parameters['ajax_page_state[theme_token]'] = pageState.theme_token;
      detail.parameters['ajax_page_state[libraries]'] = pageState.libraries;
    }
  });

It would be great if there is a convenient way to opt-out the manipulation of the request url.

There are also other things that need opt-out, for example attaching behaviors. There might be situations where a developer needs to apply very specific attachment of behaviors.

Remaining tasks

User interface changes

Introduced terminology

API changes

Data model changes

Release notes snippet

Comments

mxh created an issue. See original summary.

mxh’s picture

Issue summary: View changes
mxh’s picture

Issue summary: View changes
mxh’s picture

Issue summary: View changes
mxh’s picture

Issue summary: View changes
mxh’s picture

nod_’s picture

Could you try #3546105: Automatically manage _wrapper_format for HTMX requests and clean up ajax_page_state in urls, this should resolve the ajax_page_state ending up in the browser history.

We need to wrap the library to some extend because of a few things:

  1. Some scripts are not safe to load twice, the whole library system depends on Drupal loading a dependency only once. In some case that might be fine but with the default behavior it should not be possible to load a library twice on the page, hence we needed ajax_page_state[libraries]
  2. When requesting a page to figure out what is needed to display the content we need the theme, so we need ajax_page_state[theme] and ajax_page_state[theme_token]
  3. There are also other things that need opt-out, for example attaching behaviors. There might be situations where a developer needs to apply very specific attachment of behaviors.

    So this is the kind of expectations we need to define, and I'm very glad to see other people using this so we can discuss :)

    This is the slippery slope that granted us all the features of the Ajax framework, very powerful but complex and underused. I wouldn't want to add a way to have "Drupal-wrapped" htmx and "regular" htmx. I think we can make it so our htmx implementation does not break the expectations of regular htmx in most cases.

nod_’s picture

Also curious as to why you need the head support plugin :)

fathershawn’s picture

Component: asset library system » ajax system

I had the same question as #8 when I read the issue summary :)

mxh’s picture

Issue summary: View changes
mxh’s picture

Also curious as to why you need the head support plugin :)

I just realized today that HTMX 2.x should not require this plugin anymore, so I removed it from the IS. It seems if core/drupal.htmx would work properly with the <body> tag and would not show the ajax-related URL query parameters in the URL history, then hx-boost could work as expected.

mxh’s picture

Title: HTMX hx-boost does not work with core/drupal.html library » HTMX hx-boost does not work with core/drupal.htmx library
mxh’s picture

Could you try #3546105: Automatically manage _wrapper_format for HTMX requests, this should resolve the ajax_page_state ending up in the browser history.

Yes it resolves the flooding of the ajax_page_state arguments in the URL history. But has another effect that it only renders the main page contents. Left my findings in that issue as well.

mxh’s picture

Issue summary: View changes

I tried #3546105: Automatically manage _wrapper_format for HTMX requests and clean up ajax_page_state in urls once more and can confirm it's getting this issue forward. Updated the IS at the two bullet points identified for this. I could maybe close this one in favor of #3560659: HTMX Drupal behaviors are not applied when swapped element is body. However I have seen some problems after attached behaviors, where I'm currently not sure whether they need to be addressed as well. It seems some behavior implementations work well whereas other don't.

quietone’s picture

Version: 11.3.x-dev » 11.x-dev
longwave’s picture

Status: Active » Postponed (maintainer needs more info)

Now that #3546105: Automatically manage _wrapper_format for HTMX requests and clean up ajax_page_state in urls landed and the IS only links one other issue, is this one still needed, or should we just close this in favour of #3560659: HTMX Drupal behaviors are not applied when swapped element is body? It's not clear that there is anything else specific left to solve here.

nod_’s picture

The point left seems to be about behaviors not working nice with a boost page navigation.

We have many behaviors that do not detach cleanly, this might be one of the reasons why it's not working very well.

mxh’s picture

We have many behaviors that do not detach cleanly, this might be one of the reasons why it's not working very well.

Exactly. Could create an issue regarding these problems, then close this maybe?

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.