Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow expressions in HTML attribute names for certain types #326

Closed
tschuehly opened this issue Jan 30, 2024 · 9 comments
Closed

Allow expressions in HTML attribute names for certain types #326

tschuehly opened this issue Jan 30, 2024 · 9 comments

Comments

@tschuehly
Copy link
Contributor

Currently If I put an expression in the html next to an attribute:

 @if( item.action instanceof HTMXAction action)
        <summary
                ${action}
                hx-get="${action.type() == Type.GET ? action.path(): null }"
                hx-post="${action.type() == Type.POST ? action.path(): null }"
                hx-target="${action.target()}"
        >
        </summary>
@endif

I get this error
Illegal HTML attribute name ${action}! Expressions in HTML attribute names are not allowed.

In our use case we have a record that represents HTMX attributes:
public record HTMXAction(String path, String target, Type type, Swap swa)

According to this it is for html sanitation -> #300 (comment)

I think there are several ways to implement this while still allowing sanitation .

One way would be to have a certain type similar to Content that would allow for expressions in attributes.

public class HtmxAction implements HtmlAttributeList{
   private final String htmxType = "hx-get";
  private final String path = "/helloWorld";
   @Override
  public void writeTo(TemplateOutput output){
     output.writeAttribute(htmxType, path)
  }
}

What do you think about this idea?

It would allow to have much cleaner html templates

@casid
Copy link
Owner

casid commented Jan 31, 2024

Sounds complicated to me.

If I recall correctly there has been a similiar issue: #256 Maybe one of the solutions there would help?

@tschuehly
Copy link
Contributor Author

Ok, thanks for the pointer.
Will take a look next week!

@tschuehly
Copy link
Contributor Author

Hey @casid.

Finally got some time to try it out. I tried it out both with $unsafe and the custom Policy, but it does not behave like I would expect it

public static final String htmx = "hx-get=/helloWorld hx-swap=outerHTML";

This HTML:
<div ${htmx} >
is rendered to this:

this:
<div ${htmx} = "" >
is rendered to
<div hx-get="/helloWorld" hx-swap="outerHTML" =="" ""=""></div>

What do you think?

@casid
Copy link
Owner

casid commented Mar 21, 2024

Ugh, that's indeed unexpected!

Problem is, that $unsafe{htmx} / ${htmx} is parsed as attribute name and thus not evaluated by jte.

I've pushed a fix for this, could you have a try if this improves for you with the latest snapshot version?

casid added a commit that referenced this issue Mar 21, 2024
@tschuehly
Copy link
Contributor Author

What is the maven Repository URL for snapshots?
I tried https://s01.oss.sonatype.org/content/repositories/snapshots/ but it didn't find it.

@casid
Copy link
Owner

casid commented Mar 21, 2024

@tschuehly you can give it a try via jitpack: https://jitpack.io/#casid/jte/-SNAPSHOT

@tschuehly
Copy link
Contributor Author

@casid
Works with the SNAPSHOT!

@checketts
Copy link
Contributor

@tschuehly I'm also interested in creating a helper for htmx attributes. Do you have an example of what is working for you?

My goal is to make something like this work:

@param hx: HtmxHelper

<div ${hx.get(url="/my/url/"+item.id, swap="outerHTML", target="someId")}>Click me</div>

That would generate:

<div hx-get="/my/url/123" hx-swap="outerHTML" hx-target="someId">Click me</div>

My helper would handle the escaping if $unsafe were needed.

@tschuehly
Copy link
Contributor Author

tschuehly commented Apr 4, 2024

@checketts
Here I have an example of a config that works: tschuehly/htmx-spring-workshop@731c0f3

I'm not really sure how to approach this the best. I really come to like using static public final variables to make it easy to see what controller endpoint htmx is calling:

<button hx-get="${URI(GET_EDIT_USER_MODAL,uuid)}"
               hx-target="#${MODAL_CONTAINER_ID}">
          <img src="/edit.svg">
</button>
  public static final String GET_EDIT_USER_MODAL = "/save-user/modal/{uuid}";

  @GetMapping(GET_EDIT_USER_MODAL)
  public ViewContext editUserModal(@PathVariable UUID uuid) {
    return editUserComponent.render(uuid);
 }

UserRowComponent

For the templates you could create a HTMX object that is then stringified to htmx attributes.
In a Spring specific context I'm thinking of maybe creating a RequestMapping annotation that takes that HTMX object and creates a mapping. This way you still have the easy navigation where it is used.

maybe interesting to you aswell:
HtmxUtil.java

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants