htmxr registers a plumber2 serializer named htmx, which sends any
htmltools object as text/html. Use it on every route that returns
markup built with htmxr, whether that is a full page or a fragment:
Details
#* @get /rows
#* @serializer htmx
function(query) {
hx_table_rows(diamonds, columns = c("cut", "price"))
}The serializer plumber2 ships as html only understands a bare string or a
single htmltools::tags element. A tagList — what hx_table_rows() and
most fragment helpers return — matches neither, so it falls through to
plumber2's XML branch and is sent as unusable markup, with a 200 status
and no error. Reaching for @serializer none sidesteps that, but labels the
response text/plain.
htmx handles both, and always sets text/html:
tagListand single tags (as returned byhx_page(),hx_table_rows())strings marked with
htmltools::HTML()plain character vectors, concatenated as-is
NULL, sent as an empty body — useful for a swap that clears its target
Anything else is an error rather than malformed markup. Content that is not htmltools output — an SVG device string, JSON — belongs on the matching plumber2 serializer instead.
The serializer is registered when htmxr is loaded, so library(htmxr) at
the top of your API file is enough to make @serializer htmx resolve.
