Hoppa till huvudinnehåll

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? 🤔

  1. Enkelhet 🌟: Mindre kod, färre beroenden och enklare att förstå
  2. Prestanda ⚡️: Go är snabbt, och HTMX minimerar JavaScript-overhead
  3. Serverdriven 🖥️: All din applikationslogik finns på servern
  4. Progressiv förbättring 📈: Din app fungerar även utan JavaScript
  5. Snabb utveckling 🏃‍♀️: Fokusera på funktionalitet istället för komplexitet

Installation på Windows 🔧

Steg 1: Installera Go 🐹

  1. Gå till https://go.dev/dl/
  2. Ladda ner Go för Windows
  3. Kör installationsfilen och följ anvisningarna
  4. Verifiera installationen genom att öppna PowerShell och köra:
go version

Steg 2: Konfigurera din utvecklingsmiljö 🛠️

  1. Skapa en ny mapp för ditt projekt:
mkdir todo-htmx-go
cd todo-htmx-go
  1. Initialisera ett Go-projekt:
go mod init todo-app

Steg 3: Installera go-templ 📦

go install github.com/a-h/templ/cmd/templ@latest
Tips!

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>
}
OBS!

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

  1. "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
  2. Templates genereras inte

    • Kör alltid templ generate efter att du ändrat .templ filer
    • Kontrollera att filnamnet slutar med .templ
  3. 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:

  1. Filtrera todos: Visa endast oavslutade uppgifter
  2. Redigera text: Gör det möjligt att ändra todo-texten
  3. Prioritering: Lägg till prioritetsnivåer
  4. Kategorier: Organisera todos i olika listor
  5. Användarkonton: Lägg till inloggning och personliga listor
Resurser för fortsatt lärande