Getting Started with HTMX and Go
Using HTMX and Go to build web applications involves creating a backend using Go (commonly known as Golang) and integrating HTMX on the frontend for dynamic and interactive functionalities.
What is HTMX?
HTMX is a JavaScript library that enables dynamic behavior by leveraging HTML attributes, allowing you to create web applications with minimal JavaScript code.
HTMX is designed with a REST backend in mind, providing a lightweight SPA-like feel by replacing and rendering individual components in server responses instead of the entire page.
Below is a step-by-step guide on building a simple web application using HTMX and Go:
Example 1
1. Set up your development environment
Make sure you have Go installed on your computer. You can download it from the official website: https://golang.org/dl/
2. Create a Go project
Create a new directory for your project and initialize it as a Go module:
mkdir your_project_name
cd your_project_name
go mod init example.com/your_project_name
3. Create a simple Go server
Create a file named main.go in the project directory:
// main.go
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, HTMX!")
})
http.ListenAndServe(":8080", nil)
}
4. Integrating HTMX into your HTML
Create an HTML file in your project directory, for example, index.html:
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTMX Go App</title>
<script src="https://unpkg.com/htmx.org@1.7.0/dist/htmx.min.js"></script>
</head>
<body>
<h1 id="greeting" hx-get="/api/greeting">Loading...</h1>
</body>
</html>
5. Creating API endpoints in Go
Modify your main.go file to include API endpoints:
// main.go
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "index.html")
})
http.HandleFunc("/api/greeting", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, HTMX from Go!")
})
http.ListenAndServe(":8080", nil)
}
6. Run your Go application
Use the following command to run your Go application:
go run main.go
Visit http://localhost:8080
in a web browser, and you should see your web application running with HTMX support.
Example 2
This UI and backend are implemented with just 150 lines of code (including HTML)!
- Start by creating a simple TODO resource.
package main
import "github.com/calvinmclean/babyapi"
type TODO struct {
babyapi.DefaultResource
Title string
Description string
Completed bool
}
func main() {
api := babyapi.NewAPI[*TODO](
"TODOs", "/todos",
func() *TODO {return &TODO{} },
)
api.RunCLI()
}
- Adding HtmlX
In order to add HTMX UI on top of this, here’s what we need to do:
(1) Implement the babyapi.HTMLer interface for the TODO resource.
(2) Use the new babyapi.HTMLer type with api.SetGetAllResponseWrapper to render the response for /todosHTML.
(3) Write a template for the HTMX frontend with the following features:
- List all TODOs in a table.
- Buttons for marking items as completed and deleting them.
- Automatically append new TODOs with events sent from the server.
- Form for creating new TODOs.
(4) Use HTML instead of JSON for the response:
type HTMLerinterface {
HTML(*http.Request) string
}
HTML(*http.Request) method can be implemented as follows:
const todoRowTemplate = `...`
func (t *TODO) HTML(*http.Request) string {
tmpl := template.Must(
template.New("todoRow").Parse(todoRowTemplate),
)
return babyapi.MustRenderHTML(tmpl, t)
}
This method simply renders a template from a string and executes it with babyapi.MustRenderHTML along with the TODO data.
(5) HTML template:
<tr hx-target="this" hx-swap="outerHTML">
<td>{{ .Title }}</td>
<td>{{ .Description }}</td>
<td>
{{- $disabled := "" }}
{{-if .Completed }}
{{- $disabled = "disabled" }}
{{- end -}}
<button
hx-put="/todos/{{ .ID }}"
hx-headers='{"Accept": "text/html"}'
hx-include="this"
{{ $disabled }}>
<!-- Include entire TODO itemfor idempotent PUT -->
<input type="hidden" name="Completed" value="true">
<input type="hidden" name="Title" value="{{ .Title }}">
<input type="hidden" name="Description" value="{{ .Description }}">
<input type="hidden" name="ID" value="{{ .ID }}">
Complete
</button>
<button hx-delete="/todos/{{ .ID }}" hx-swap="swap:1s">
Delete
</button>
</td>
</tr>
This template will create an HTML table row (<tr>
) to display the title and description of a TODO. The row also includes buttons to mark the item as complete or delete it.
In addition to regular HTML, we can use HTMX attributes to control the interaction with the backend.
Reference: https://www.jdon.com/71227.html