wimdeblauwe / htmx-spring-boot

Spring Boot and Thymeleaf helpers for working with htmx
Apache License 2.0
497 stars 48 forks source link

Add support for hx:vals for maps directly #27

Closed checketts closed 1 year ago

checketts commented 1 year ago

hx-vals allows for json data to be added to a request. However that means it needs to be escaped with all the correct quotes like so:

hx:vals="${'{"id":"' + myId + '"}'}"

which is rendered as: hx-vals="{'id': 1234}" but is very hard to write and read.

Thymeleaf supports inline maps like so:

hx:vals="${ {id: id } }"

which renders as hx-vals="{id: 1234}" (note the lack of quotes for the attribute name) Which is not proper JSON and htmx can't use it. I would like to propose adding support for rendering JSON (using Jackson) for hx-vals.

What do you think?

checketts commented 1 year ago

An alternative option is to add a Formatter<Map<Any,Any>> like so:

    @Bean
    fun mapFormatter(mapper: ObjectMapper) : org.springframework.format.Formatter<Map<Any,Any>> {
        return MapFormatter(mapper)
    }

    class MapFormatter(private val mapper: ObjectMapper) : org.springframework.format.Formatter<Map<Any,Any>> {
        override fun print(obj: Map<Any, Any>, locale: Locale): String {
            return mapper.writeValueAsString(obj)
        }

        override fun parse(text: String, locale: Locale): Map<Any, Any> {
            return mapper.readValue(text)
        }
    }

Then use the double curly {{ to trigger a formatter as well as the inline map creation like so:

hx:vals="${{ {id: id } }}"

I'm happy to document this approach in the README if that is the preferred option.

wimdeblauwe commented 1 year ago

I agree we should do something for hx:vals, using those &quot; things is making it very hard. But not sure what the best way forward is.

Does your first proposal mean that if you write hx:vals="${ {id: id } }" it would somehow automatically get rendered as hx-vals='{"id": 1234}' in the HTML ?

wimdeblauwe commented 1 year ago

Do you have a link to the Thymeleaf documentation about those inline maps ?

checketts commented 1 year ago

It appears to be a SPEL feature (https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#expressions-inline-maps) I haven't found anything in Thymeleaf's documetation for it yet.

checketts commented 1 year ago

Does your first proposal mean that if you write hx:vals="${ {id: id } }" it would somehow automatically get rendered as hx-vals='{"id": 1234}' in the HTML ?

Correct

wimdeblauwe commented 1 year ago

Seems like a good addition if you could do that.

checketts commented 1 year ago

Will do