Skip to content

Commit

Permalink
feat: templ templates
Browse files Browse the repository at this point in the history
  • Loading branch information
joerdav committed Jul 4, 2023
1 parent 9e3c6c2 commit e918ba6
Show file tree
Hide file tree
Showing 8 changed files with 261 additions and 60 deletions.
2 changes: 1 addition & 1 deletion content/posts/goodbye-world.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Every time `Click Me!` is clicked, a request is sent to fetch static template `/

{{< html.inline >}}
<button
hx-get="/goodbyeworld.html"
hx-get="{{ .Site.Params.apiBaseUrl }}/goodbyeworld.html"
hx-trigger="click"
hx-target="#goodbye"
hx-swap="beforeend">
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
module github.com/acaloiaro/hugo-htmx-go-template

go 1.20

require github.com/a-h/templ v0.2.304
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
github.com/a-h/templ v0.2.304 h1:vIgCNazkW6NiYifFIGYNRfBkoBzOMZMO1NibIayzihE=
github.com/a-h/templ v0.2.304/go.mod h1:3oc37WS5rpDvFGi6yeknvTKt50xCu67ywQsM43Wr4PU=
1 change: 0 additions & 1 deletion partials/goodbyeworld.html

This file was deleted.

10 changes: 0 additions & 10 deletions partials/helloworld.html

This file was deleted.

18 changes: 18 additions & 0 deletions partials/templates.templ
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package partials

templ HelloWorld(name string) {
<div>
<p>This content is coming from our API server. It's a standard <strong>text/html</strong>template: <strong>partials/helloworld.html</strong>. The template has a single variable named <strong>Name</strong>, which it greets below.</p>
</div>
<p>If you set the <strong>name</strong>URL param, it greets you by name, e.g. <a href="/posts/hello-world/?name=foobar">/posts/hello-world/?name=foobar</a></p>
@HelloWorldGreeting(name)
}

templ HelloWorldGreeting(name string) {
<h3>Greeting: Hello, { name }!</h3>
}

templ GoodbyeWorld() {
<p>Goodbye, World!</p>
}

213 changes: 213 additions & 0 deletions partials/templates_templ.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

73 changes: 25 additions & 48 deletions server.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package main

import (
"bytes"
"embed"
"fmt"
"html/template"
"io/fs"
"log"
"net/http"

"github.com/a-h/templ"
"github.com/acaloiaro/hugo-htmx-go-template/partials"
)

//go:embed all:public
Expand All @@ -20,9 +21,25 @@ func main() {
// Serve all hugo content (the 'public' directory) at the root url
mux.Handle("/", http.FileServer(http.FS(serverRoot)))

cors := func(h http.Handler) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// in development, the Origin is the the Hugo server, i.e. http://localhost:1313
// but in production, it is the domain name where one's site is deployed
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, hx-target, hx-current-url, hx-request")
if r.Method == "OPTIONS" {
w.WriteHeader(http.StatusNoContent)
return
}
h.ServeHTTP(w, r)
}
}

// Add any number of handlers for custom endpoints here
mux.HandleFunc("/hello_world", helloWorld)
mux.HandleFunc("/hello_world_form", helloWorldForm)
mux.HandleFunc("/goodbyeworld.html", cors(templ.Handler(partials.GoodbyeWorld())))
mux.HandleFunc("/hello_world", cors(http.HandlerFunc(helloWorld)))
mux.HandleFunc("/hello_world_form", cors(http.HandlerFunc(helloWorldForm)))

fmt.Printf("Starting API server on port 1314\n")
if err := http.ListenAndServe("0.0.0.0:1314", mux); err != nil {
Expand All @@ -36,30 +53,15 @@ func main() {
//
// It responds with the the HTML partial `partials/helloworld.html`
func helloWorld(w http.ResponseWriter, r *http.Request) {
// in development, the Origin is the the Hugo server, i.e. http://localhost:1313
// but in production, it is the domain name where one's site is deployed
w.Header().Set("Access-Control-Allow-Origin", "*")

if r.Method == "OPTIONS" {
w.WriteHeader(http.StatusNoContent)
return
}

name := r.URL.Query().Get("name")
if name == "null" || name == "" {
name = "World"
}

tmpl := template.Must(template.ParseFiles("partials/helloworld.html"))
var buff = bytes.NewBufferString("")
err := tmpl.Execute(buff, map[string]string{"Name": name})
if err != nil {
ise(err, w)
if err := partials.HelloWorld(name).Render(r.Context(), w); err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}

w.WriteHeader(http.StatusOK)
w.Write(buff.Bytes())
}

// this handler accepts POST requests to /hello_world_form
Expand All @@ -68,18 +70,6 @@ func helloWorld(w http.ResponseWriter, r *http.Request) {
//
// It responds with a simple greeting HTML partial
func helloWorldForm(w http.ResponseWriter, r *http.Request) {
// in development, the Origin is the the Hugo server, i.e. http://localhost:1313
// but in production, it is the domain name where one's site is deployed
// for this demo, we're using `*` to keep things simple
w.Header().Set("Access-Control-Allow-Origin", "*")

if r.Method == "OPTIONS" {
w.Header().Set("Access-Control-Allow-Methods", "POST")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, hx-current-url, hx-request")
w.WriteHeader(http.StatusNoContent)
return
}

name := "World"
// The name is not in the query param, let's see if it was submitted as a form
if err := r.ParseForm(); err != nil {
Expand All @@ -88,23 +78,10 @@ func helloWorldForm(w http.ResponseWriter, r *http.Request) {
}

name = r.FormValue("name")
// we're dealing with a really simple template; let's use an inline string instead of a whole separate file for this
// one
tmpl, err := template.New("form_response").Parse("<h3>Greeting: Hello, {{ .Name }}!</h3>")
if err != nil {
ise(err, w)
if err := partials.HelloWorldGreeting(name).Render(r.Context(), w); err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}

var buff = bytes.NewBufferString("")
err = tmpl.Execute(buff, map[string]string{"Name": name})
if err != nil {
ise(err, w)
return
}

w.WriteHeader(http.StatusOK)
w.Write(buff.Bytes())
}

func ise(err error, w http.ResponseWriter) {
Expand Down

0 comments on commit e918ba6

Please sign in to comment.