- Issue created by @fathershawn
- πΊπΈUnited States fathershawn New York
Missed bringing over the Twig function
The Needs Review Queue Bot β tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide β to find step-by-step guides for working with issues.
- πΊπΈUnited States fathershawn New York
Applied a suggestion and will refactoring some improvements inspired by @larowan review. A maintainer should add him to the credits.
- πΊπΈUnited States fathershawn New York
All tests green.
There are two open questions:
- π«π·France nod_ Lille
I don't understand why we need the single quote. If you add a JSON::encode(), to the process assets MR it just works.
$build['replace'] = [ '#type' => 'html_tag', '#tag' => 'button', '#attributes' => [ 'type' => 'button', 'name' => 'replace', 'data-hx-get' => $url->toString(), 'data-hx-select' => 'div.ajax-content', 'data-hx-target' => '[data-drupal-htmx-target]', // add this part 'data-hx-vals' => Json::encode(['test' => 'ok']), ], '#value' => 'Click this', '#attached' => [ 'library' => [ 'core/drupal.htmx', ], ], ];
It doesn't matter that the source html doesn't look pretty. Once it's in the JS it's the correct value.
- πΊπΈUnited States fathershawn New York
That's a great question! I didn't think it would but I didn't try. I'll repeat the experiment with an attribute value selector and remove the complexity. Simpler is better!!
- πΊπΈUnited States fathershawn New York
Confirmed! I can now remove a trait and a class - thank you @nod_ :)
I altered the render arrays in the test module to
$build['replace'] = [ '#type' => 'html_tag', '#tag' => 'button', '#attributes' => [ 'type' => 'button', 'name' => 'replace', 'data-hx-get' => $url->toString(), 'data-hx-select' => 'div.ajax-content', 'data-hx-target' => 'div[data-drupal-htmx-target="insert-here"]', ], '#value' => 'Click this', '#attached' => [ 'library' => [ 'core/drupal.htmx', ], ], ]; $build['content'] = [ '#type' => 'container', '#attributes' => [ 'data-drupal-htmx-target' => 'insert-here', 'class' => ['htmx-test-container'], ],
Which produces
data-hx-target="div[data-drupal-htmx-target="insert-here"]"
through the standard string attribute. HTMX worked as expected. - πΊπΈUnited States fathershawn New York
All threads resolved - all tests passing :)
- πΊπΈUnited States fathershawn New York
We agreed in Slack to pause on this builder while we work on π Refactor BigPipe to use HTMX Active using attributes that are "hand-rolled."
- πΊπΈUnited States fathershawn New York
Coming back to this now - we needed the htmx javascript API in π Refactor BigPipe to use HTMX Active but not attributes.
- Issue was unassigned.
- Status changed to Needs review
about 2 months ago 8:00pm 15 July 2025 - πΊπΈUnited States fathershawn New York
Tagged
\Drupal\Core\Template\HtmlAttributeInterface
as @internal as that seems consistent with the policy on Attribute class internals β . - πΊπΈUnited States fathershawn New York
Discussed and agreed in Slack that a single change record and release note will cover:
- π DX object to manage htmx attributes Active
- π DX object to manage htmx headers Active
- π DX object to collect and manage HTMX behaviors Active
- π Define and process an #htmx render array key Active
- πΊπΈUnited States fathershawn New York
Based on #26 and the description of the tag (A change record needs to be drafted before an issue is committed.) I'm removing the CR tag from this issue as these are sequential dependencies and the tag belongs on final component.
- πΊπΈUnited States fathershawn New York
Reading through the governance doc I am marking this for framework manager review since it is blocking other work.
- πΊπΈUnited States fathershawn New York
I brought the summary up to date with the code. We have 5 unresolved comment threads on the MR. Most open threads have a response.
Following a comment from @catch I updated the code in
\Drupal\Core\Template\HtmxAttribute
for:- ::get
- ::post
- ::put
- ::patch
- ::delete
- ::pushUrl
- ::replaceUrl
to pass in and instance of
CacheableDependencyInterface
and collect the cacheable metadata emitted by the Url object.There is an open question about the advisability of adding return types in
\Drupal\Core\Template\Attribute
. I understand this class to be internal by policy but maybe that's not right?The other 3 open threads all have answers.
I have time to move this project forward to let's get this to RTBC so it can be committed and work can start on the next layer!!
- πΊπΈUnited States fathershawn New York
@catch can you give guidance about adding return types to
\Drupal\Core\Template\Attribute
?I hit a name collision on the BC policy with the Attribute name (As you and @nicxvan noted that was for PHP attributes). But it also seems to be permitted with these:
PHP and JavaScript classes β
In general, only interfaces can be relied on as the public API. With the exception of base classes, developers should generally assume that implementations of classes will change, and that they should not inherit from classes in the system, or be prepared to update code for changes if they do. See also more specific notes below.Public methods not specified in an interface β
Public methods on a class that aren't on a corresponding interface are considered @internal.We are adding an interface in this issue, but there no interface for this class now. @larowan seemed to think it was okay here: https://git.drupalcode.org/project/drupal/-/merge_requests/12097#note_51...
The Needs Review Queue Bot β tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide β to find step-by-step guides for working with issues.
- πΊπΈUnited States fathershawn New York
Thank you @phenaproxima for improving the code with your questions and suggestions. I've resolved all comments with either updates or answers except those related to return types (see #30). All tests are passing.
- π¬π§United Kingdom catch
Given @larowlan's:
I did a search of contrib for classes that extend this where these new return types might be a BC break and could only find on in display suite, that was only adding a new method - and one in htmx which also didn't override any of the methods we're adding too here So I think this change is fine to do in a minor release, with a change record
and https://www.drupal.org/about/core/policies/core-change-policies/bc-polic... β I think we're OK to add the return type hints to
Attribute
here with a change record. It's allowed under the bc policy, and we can be fairly confident it won't break any existing code. - πΊπΈUnited States nicxvan
Ok that was tedious, but I clicked on all documentation links and confirmed they align except the ones that I have suggestions for.
I also reviewed all changes and have been following. I think this is ready assuming the three suggestions are accepted and tests pass.
Only remaining substantial question I have is where does sanitization happen?
I see some attributes do check the expected value is a boolean, but I don't see anything else, is that all handled upstream of this? - πΊπΈUnited States fathershawn New York
@nicxvan First, thank you for so carefully checking the tedious mundane details! Suggestions committed and test updated for the one method name fix.
Sanitization happens in the attribute value object's
::__toString
method. They all extend AttributeValueBase which sanitizes the name property. We addAttributeJson
in this MR, and follow this pattern. - πΊπΈUnited States nicxvan
I think this is ready, the extensive feedback has been addressed!
- πΊπΈUnited States fathershawn New York
@catch @larowlan @nod_ A CacheableMetada parameter was added to methods that take a URL based on feedback. This complicates calling these methods within Twig as the caching has already bubbled.
Does this change the utility of a providing the attribute object within Twig? Should we drop that function from this MR?
- π«π·France nod_ Lille
I'd drop it. We can always add a followup to add it and we can figure out the problems without holding the working part of the MR
- πΊπΈUnited States fathershawn New York
Thanks @nod_ !!
Removed the twig function from this issue's MR and the change record. It is extra.
CR is updated with the full picture of how all 4 issue changes work together.
- First commit to issue fork.
- πΊπΈUnited States fathershawn New York
few cosmetic feedbacks
Suggested changes made.
- πΊπΈUnited States fathershawn New York
Unrelated toolbar tests failing. Rebasing onto HEAD.
- πΊπΈUnited States fathershawn New York
Required tests passing. The php 8.5 test seems to be failing in general due to widespread deprecations.
- πΊπΈUnited States nicxvan
I think this is rtbc, I reviewed the comments from nod and the two commits since my initial rtbc.
- π«π·France nod_ Lille
We need the empty URL thing for the post/patch/delete/put methods too
- πΊπΈUnited States fathershawn New York
Re: #48 - okay. It's not documented at
- https://htmx.org/attributes/hx-post/
- https://htmx.org/attributes/hx-delete/
- https://htmx.org/attributes/hx-patch/
- https://htmx.org/attributes/hx-put/
as it is for get. Did you find support for all five in the code @nod_? It will make our code simpler so I'm going ahead. It would be good to document in a comment here for future reference with a link to their code or other documentation.
- πΊπΈUnited States fathershawn New York
Made all five http verb methods operate the same way.
- πΊπΈUnited States fathershawn New York
The empty URL behavior discussed in #48 & #49 is in the
issueAjaxRequest
function ofhtmx.js
As of this note this can be seen at https://github.com/bigskysoftware/htmx/blob/master/src/htmx.js#L4426Turns out this goes back to RFC 2396 on the URI specification co-authored by Tim Berners-Lee in 1998 no less!
4.2. Same-document References
A URI reference that does not contain a URI is a reference to the current document... - π«π·France nod_ Lille
We've had a discussion on slack with @fathershawn about this.
The current approach of the MR is not ideal:
- All the HTMX-specific helpers and documentation lives in the
\Drupal\Core\Template
namespace - Values are transformed to an AttributeValueBase right away, making it unusual to work with in alter/preprocesses
Thankfully we can fix it by moving things around:
- Move the builder object to the
\Drupal\Core\Htmx
namespace - Make it work more like
CacheableMetadata
, with anapplyTo()
andcreateFromRenderArray
(we need this to unserialize the json attributes) methods that we call on a render array to augment it. - In the applyTo method, save all the data as attributes in the render array
#attributes
key, and json_encode what needs to be json_encoded and let the existing code handle the attribute rendering
- All the HTMX-specific helpers and documentation lives in the
- πΊπΈUnited States nicxvan
Values are transformed to an AttributeValueBase right away, making it unusual to work with in alter/preprocesses
Great catch!
Is there a test we can add showing this, or does it need implementation for that? - π¦πΊAustralia larowlan π¦πΊπ.au GMT+10
nod_ β credited larowlan β .
- πΊπΈUnited States phenaproxima Massachusetts
nod_ β credited phenaproxima β .
- π«π·France nod_ Lille
@nicxvan not sure how we'd test this reliably. Maybe check if there are any AttributeValueBase in the #attributes array at the preprocess step? but then which render array do we test? or maybe a bunch of asserts?
@fathershawn: now that you're a maintainer you can give credit, credits are given for closed issues now too :)
- π«π·France pdureau Paris
In the applyTo method, save all the data as attributes in the render array #attributes key, and json_encode what needs to be json_encoded and let the existing code handle the attribute rendering
I am not familiar about the
applyTo
method from CacheableMetadata, is it resolved late? Ideally, we keep the HTML values separated as long as possible and we move them to#attributes
just before rendering.We are working on at least on two other features with attributes values which must be set and kept distinct from
#attributes
but merged to#attributes
before rendering: β¨ Add a style utility API Active and β¨ Add a CSS variables API Active . So a generic behavior and/or standard "way" may be useful.