Can HTMX target a single DOM element attribute rather than the whole element?

494 views Asked by At

I want to replace a single attribute on a single DOM element using HTMX, something easy to do in JS but I can't seem to figure out the best way in HTMX to do it.

My specific use-case is an input field where I want to change the attribute aria-invalid without disturbing anything else.

  1. According to docs hx-preserve does what I want in general except for the specific case I want (preserver focus, caret, etc.). Suggests morphing.
  2. Morphing should work, but I have to include another script library (Idiomorph or morphdom-swap) or use v2.0 of Htmx (not released yet) to get it out of the box. Overcomplicated it seems to replace a single attribute.
  3. Use an event like htmx:afterSwap to run a small snippet of JS code to set the attribute (seems easiest but is this a bad idea?)
1

There are 1 answers

0
mr.b On

After trying many ways, here is the simplest I found so far. Maybe somebody else has a better way.

  1. I created a list under the input to show issues. Set the input hx-target="next ul"
<input id="username" name="username" required hx-boost="true" hx-target="next ul" hx-swap="outerHTML" hx-get="/validate/username" hx-trigger="change, keyup delay:200ms changed" aria-invalid="">
  1. I boosted the element after which holds the validation errors, and it also has an embedded script which I call from the element's hx-on:htmx:load event when it's triggered.
<ul hx-boost="true" hx-trigger="load" hx-on:htmx:load="update_username_attribute()">
    <li class="{{form_metadata['character_constraint_class']}}">Only a-z, A-Z, 0-9, - and _</li>
    <li class="{{form_metadata['dash_constraint_class']}}">Doesn't begin or end with -</li>
    <li class="{{form_metadata['length_constraint_class']}}">Length of 4-39 characters</li>
    <li class="{{form_metadata['unique_constraint_class']}}">Is unique</li>
    <script>
        function update_username_attribute() {
            element = document.getElementById("username");
            element.setAttribute("aria-invalid", "{{form_metadata['aria_invalid']}}");
        }
    </script>
</ul>

Note: I wanted to just do this from the input element, but I couldn't get hx-on:htmx:afterSwap to work at all. Event fires in debugger, but my code not executed for that event for some reason but it works for others. E.g. If I changed it to hx-on:htmx:afterRequest it works.