How does it compare to Lucky framework template methods?
You also mentioned front-end frameworks like Svelte. Is this reactive on the front-end, just like Svelte, or uses backend rendering?
It is Backend rendering, but one could create separately custom HTML tags with Svelte (for instance) that would do some client-side stuff or alternatively use a prefabricated HTML/JS/Css object
(widget) which does its own client-side stuff (like, e.g. an editor widget written in javascript)…
Using forms, POST and reloading an entire is no longer required, widgets (elements) can modify themselves, using Ajax.
Ajax requests are made possible using HTMX.
HTMX uses JS in a transparent manner (behind the scenes), not explicit JS coding is required.
Snippet :
#########
# Form 1
#########
class Form1
include Blueprint::HTML
def initialize(@state : State = state)
end
private def blueprint
# including 'Links'widget
render Links.new
# Global style
style { picoCSS }
# Local widget Style
style { LocalCSS }
script src: "https://unpkg.com/htmx.org@1.9.6"
div class: "main" {
br
article {
input type: "text"
}
br
article {
# first form (uses Ajax, via HTMX) : Only redraws the target element, NOT the enrire page.
form {
input "type": "submit", "value": "Increment counter, version 1", "hx-post": "/increment_2", "hx-target": "#counter"
}
br
# second form : Classical form redraws the entire page
form action: "/increment_1", method: "POST" {
input type: "submit", value: "increment counter, version 2"
}
br
# classical HTML form
form action: "/reset_1", method: "POST" {
input type: "submit", value: "Reset counter"
}
}
article {
label id: "counter" { "State : #{@state.count}" }
label { "State : #{@state.lname}" }
label { "State : #{@state.fname}" }
}
}
div class: "message" { "state demo" }
end
end
With Ajax and actions defined alongside forms, the code looks more and more like Vue.js or React.js, except the entire app code uses Crystal both on front-end and back-end.
The complete example Is in the repo:
class Form1
include Blueprint::HTML
def initialize(@state : State = state)
end
private def blueprint
# including 'Links'widget
render Links.new
div class: "main" {
br
article {
input type: "text"
}
br
article {
# first form (uses Ajax, via HTMX) : Only redraws the target element, NOT the enrire page.
form {
button "hx-post": "/increment_2", "hx-target": "#counter" {
"Increment counter, version 1"
}
}
br
# second form (Classical form) redraws the entire page
form action: "/increment_1", method: "POST" {
input type: "submit", value: "increment counter, version 2"
}
br
# classical HTML form
form action: "/reset_1", method: "POST" {
input type: "submit", value: "Reset counter"
}
}
article {
label id: "counter" { "State : #{@state.count}" }
label { "State : #{@state.lname}" }
label { "State : #{@state.fname}" }
}
}
div class: "message" { "state demo" }
end
end
# Form action which refreshes the entire form
# (deprecated)
def increment_1(env : HTTP::Server::Context, state : State)
state.count = state.count + 1
Form1.new(state).to_html
end
# Form action which refreshes only one targeted element of the form
# (recommended)
def increment_2(env : HTTP::Server::Context, state : State)
state.count = state.count + 1
"<div> State: #{state.count} </div>"
end
The server (back-end) of the app seems to work correctly. but not the front-end when using HTMX.
There seems to be a problem when using HTMX in Webview under Linux.
This can be demonstrated by starting one of the two apps on the command-line and then (while the app is still running) point a browser to the URL used by the server (the default is http://127.0.0.1:3000/root or http://localhost/root )
The app front-end behaves as expected in a regular browser.
It seems therefore that HTMX does not play well with Webview.
HTMX must be using some clever javaScript that Webview does not provide or does not interpret correctly.
I will look into it and try to debug the HTMX issue with Webview under Linux.
Fixes in the meantime:
Not use Ajax (i.e. not use HTMX), use the formulation withe regular HTTP requests.
Alternatively : Use a regular browser as a front-end.