Bygg en Todo-app med HTMX och Go 🚀🎯
Vad är HTMX och Go? 🔍
HTMX är ett modernt JavaScript-bibliotek som låter dig bygga dynamiska webbapplikationer med minimal JavaScript. Istället för att skriva komplex frontend-kod kan du använda enkla HTML-attribut för att skapa interaktiva användargränssnitt! ⚡️
Go är ett programmeringsspråk skapat av Google som är känt för sin enkelhet och prestanda. Det är perfekt för att bygga webbservers och API:er! 🐹
go-templ är ett templating-bibliotek för Go som gör det enkelt att generera HTML på serversidan. 📝
Varför HTMX + Go? 🤔
- Enkelhet 🌟: Mindre kod, färre beroenden och enklare att förstå
- Prestanda ⚡️: Go är snabbt, och HTMX minimerar JavaScript-overhead
- Serverdriven 🖥️: All din applikationslogik finns på servern
- Progressiv förbättring 📈: Din app fungerar även utan JavaScript
- Snabb utveckling 🏃♀️: Fokusera på funktionalitet istället för komplexitet
Installation på Windows 🔧
Steg 1: Installera Go 🐹
- Gå till https://go.dev/dl/
- Ladda ner Go för Windows
- Kör installationsfilen och följ anvisningarna
- Verifiera installationen genom att öppna PowerShell och köra:
go version
Steg 2: Konfigurera din utvecklingsmiljö 🛠️
- Skapa en ny mapp för ditt projekt:
mkdir todo-htmx-go
cd todo-htmx-go
- Initialisera ett Go-projekt:
go mod init todo-app
Steg 3: Installera go-templ 📦
go install github.com/a-h/templ/cmd/templ@latest
Se till att din PATH inkluderar Go's bin-katalog! Om templ
inte hittas, lägg till %USERPROFILE%\go\bin
till din PATH.
Skapa din första server 🌐
Grundläggande serverstruktur
Skapa en fil som heter main.go
:
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", homeHandler)
fmt.Println("Server startar på :8080 🚀")
http.ListenAndServe(":8080", nil)
}
func homeHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "<h1>Välkommen till Todo-appen!</h1>")
}
Kör servern:
go run main.go
Öppna din webbläsare och gå till http://localhost:8080
🎉
Lägg till HTMX 🎨
Skapa en HTML-template med go-templ
Skapa en fil som heter templates.templ
:
package main
templ Layout() {
<!DOCTYPE html>
<html lang="sv">
<head>
<meta charset="UTF-8"/>
<title>Todo App</title>
<script src="https://unpkg.com/htmx.org@1.9.10"></script>
<style>
body { font-family: Arial, sans-serif; margin: 40px; }
.todo-item { margin: 10px 0; }
</style>
</head>
<body>
<h1>Min Todo-lista 📝</h1>
{ children... }
</body>
</html>
}
templ TodoList(todos []Todo) {
<div id="todo-list">
for _, todo := range todos {
@TodoItem(todo)
}
</div>
}
Efter att du skapat .templ
filer, måste du generera Go-kod från dem:
templ generate
Bygga Todo-funktionaliteten 🛠️
Definiera Todo-strukturen
Lägg till i main.go
:
type Todo struct {
ID int
Text string
Completed bool
}
var todos = []Todo{
{ID: 1, Text: "Lär dig HTMX", Completed: false},
{ID: 2, Text: "Bygga en Go-server", Completed: false},
}
Lägg till todo-formulär
Utöka din templates.templ
:
templ TodoForm() {
<form hx-post="/todos" hx-target="#todo-list" hx-swap="beforeend">
<input type="text" name="text" placeholder="Ny uppgift..." required/>
<button type="submit">Lägg till ➕</button>
</form>
}
templ TodoItem(todo Todo) {
<div class="todo-item" id={ fmt.Sprintf("todo-%d", todo.ID) }>
<input type="checkbox"
hx-put={ fmt.Sprintf("/todos/%d/toggle", todo.ID) }
hx-target={ fmt.Sprintf("#todo-%d", todo.ID) }
hx-swap="outerHTML"
if todo.Completed { checked }/>
<span if todo.Completed { style="text-decoration: line-through;" }>
{ todo.Text }
</span>
<button hx-delete={ fmt.Sprintf("/todos/%d", todo.ID) }
hx-target={ fmt.Sprintf("#todo-%d", todo.ID) }
hx-swap="outerHTML">
Ta bort 🗑️
</button>
</div>
}
Implementera HTMX-endpoints 🔌
Lägg till nya routes
Uppdatera din main.go
:
func main() {
http.HandleFunc("/", homeHandler)
http.HandleFunc("/todos", todosHandler)
http.HandleFunc("/todos/", todoHandler) // För individuella todos
fmt.Println("Server startar på :8080 🚀")
http.ListenAndServe(":8080", nil)
}
func todosHandler(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "POST":
// Hämta text från formuläret
text := r.FormValue("text")
// Skapa ny todo
newTodo := Todo{
ID: len(todos) + 1,
Text: text,
}
todos = append(todos, newTodo)
// Returnera bara den nya todo-komponenten
TodoItem(newTodo).Render(r.Context(), w)
}
}
Hantera toggle och delete
func todoHandler(w http.ResponseWriter, r *http.Request) {
// Extrahera ID från URL:en
// /todos/1/toggle -> ["", "todos", "1", "toggle"]
parts := strings.Split(r.URL.Path, "/")
if len(parts) < 3 {
http.NotFound(w, r)
return
}
id, _ := strconv.Atoi(parts[2])
switch r.Method {
case "PUT":
// Toggle completed status
for i := range todos {
if todos[i].ID == id {
todos[i].Completed = !todos[i].Completed
TodoItem(todos[i]).Render(r.Context(), w)
return
}
}
case "DELETE":
// Ta bort todo
for i, todo := range todos {
if todo.ID == id {
todos = append(todos[:i], todos[i+1:]...)
return
}
}
}
}
Felsökning och tips 🐛
Vanliga problem
-
"templ: command not found"
- Kontrollera att Go's bin-katalog finns i din PATH
- Kör:
go env GOPATH
och lägg till/bin
till den sökvägen
-
Templates genereras inte
- Kör alltid
templ generate
efter att du ändrat.templ
filer - Kontrollera att filnamnet slutar med
.templ
- Kör alltid
-
HTMX fungerar inte
- Öppna utvecklarkonsolen (F12) och kolla efter JavaScript-fel
- Verifiera att HTMX laddas korrekt
Tips för vidare utveckling 💡
- Databaspersistens: Använd SQLite för att spara todos permanent
- CSS-styling: Lägg till Tailwind CSS för snyggare design
- Validering: Lägg till serverside-validering för formulär
- Fel-hantering: Implementera bättre felmeddelanden
- Animationer: Använd HTMX:s inbyggda övergångar
Nästa steg 🚀
Nu har du grunderna! Här är några idéer för att utöka din app:
- Filtrera todos: Visa endast oavslutade uppgifter
- Redigera text: Gör det möjligt att ändra todo-texten
- Prioritering: Lägg till prioritetsnivåer
- Kategorier: Organisera todos i olika listor
- Användarkonton: Lägg till inloggning och personliga listor
- HTMX dokumentation: https://htmx.org/docs/
- Go by Example: https://gobyexample.com/
- go-templ guide: https://templ.guide/