From da517a0d22385b109858e97711f0ba7cea3d05c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20W=C3=BCstenberg?= Date: Mon, 27 Feb 2023 11:10:50 +0100 Subject: [PATCH] Add example application --- README.md | 83 +++++++++++++++++++++++++++++++++++++++++++++ cmd/example/main.go | 71 ++++++++++++++++++++++++++++++++++++++ http/http_test.go | 6 ++++ 3 files changed, 160 insertions(+) create mode 100644 cmd/example/main.go diff --git a/README.md b/README.md index a02686d..9cb9532 100644 --- a/README.md +++ b/README.md @@ -5,4 +5,87 @@ [HTMX](https://htmx.org) attributes and helpers for [gomponents](https://www.gomponents.com). +## Usage + +```shell +go get github.com/maragudk/gomponents-htmx +``` + +Example app: + +```go +package main + +import ( + "errors" + "log" + "net/http" + "time" + + g "github.com/maragudk/gomponents" + c "github.com/maragudk/gomponents/components" + . "github.com/maragudk/gomponents/html" + ghttp "github.com/maragudk/gomponents/http" + hx "github.com/maragudk/gomponents-htmx" + hxhttp "github.com/maragudk/gomponents-htmx/http" +) + +func main() { + if err := start(); err != nil { + log.Fatalln("Error:", err) + } +} + +func start() error { + now := time.Now() + mux := http.NewServeMux() + mux.HandleFunc("/", ghttp.Adapt(func(w http.ResponseWriter, r *http.Request) (g.Node, error) { + if r.Method == http.MethodPost && hxhttp.IsBoosted(r.Header) { + now = time.Now() + + hxhttp.SetPushURL(w.Header(), "/?time="+now.Format(timeFormat)) + + return partial(now), nil + } + return page(now), nil + })) + + log.Println("Starting on http://localhost:8080") + if err := http.ListenAndServe("localhost:8080", mux); err != nil && !errors.Is(err, http.ErrServerClosed) { + return err + } + return nil +} + +const timeFormat = "15:04:05" + +func page(now time.Time) g.Node { + return c.HTML5(c.HTML5Props{ + Title: now.Format(timeFormat), + Head: []g.Node{ + Script(Src("https://cdn.tailwindcss.com?plugins=forms,typography")), + Script(Src("https://unpkg.com/htmx.org")), + }, + Body: []g.Node{ + Div(Class("max-w-7xl mx-auto p-4 prose lg:prose-lg xl:prose-xl"), + H1(g.Text(`gomponents + HTMX`)), + P(g.Textf(`Time at last full page refresh was %v.`, now.Format(timeFormat))), + partial(now), + FormEl(Method("post"), Action("/"), hx.Boost("true"), hx.Target("#partial"), hx.Swap("outerHTML"), + Button(Type("submit"), g.Text(`Update time`), + Class("rounded-md border border-transparent bg-orange-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-orange-700 focus:outline-none focus:ring-2 focus:ring-orange-500 focus:ring-offset-2"), + ), + ), + ), + }, + }) +} + +func partial(now time.Time) g.Node { + return P(ID("partial"), g.Textf(`Time was last updated at %v.`, now.Format(timeFormat))) +} + +``` + + Made in 🇩🇰 by [maragu](https://www.maragu.dk/), maker of [online Go courses](https://www.golang.dk/). diff --git a/cmd/example/main.go b/cmd/example/main.go new file mode 100644 index 0000000..9f1bd12 --- /dev/null +++ b/cmd/example/main.go @@ -0,0 +1,71 @@ +package main + +import ( + "errors" + "log" + "net/http" + "time" + + g "github.com/maragudk/gomponents" + c "github.com/maragudk/gomponents/components" + . "github.com/maragudk/gomponents/html" + ghttp "github.com/maragudk/gomponents/http" + + hx "github.com/maragudk/gomponents-htmx" + hxhttp "github.com/maragudk/gomponents-htmx/http" +) + +func main() { + if err := start(); err != nil { + log.Fatalln("Error:", err) + } +} + +func start() error { + now := time.Now() + mux := http.NewServeMux() + mux.HandleFunc("/", ghttp.Adapt(func(w http.ResponseWriter, r *http.Request) (g.Node, error) { + if r.Method == http.MethodPost && hxhttp.IsBoosted(r.Header) { + now = time.Now() + + hxhttp.SetPushURL(w.Header(), "/?time="+now.Format(timeFormat)) + + return partial(now), nil + } + return page(now), nil + })) + + log.Println("Starting on http://localhost:8080") + if err := http.ListenAndServe("localhost:8080", mux); err != nil && !errors.Is(err, http.ErrServerClosed) { + return err + } + return nil +} + +const timeFormat = "15:04:05" + +func page(now time.Time) g.Node { + return c.HTML5(c.HTML5Props{ + Title: now.Format(timeFormat), + Head: []g.Node{ + Script(Src("https://cdn.tailwindcss.com?plugins=forms,typography")), + Script(Src("https://unpkg.com/htmx.org")), + }, + Body: []g.Node{ + Div(Class("max-w-7xl mx-auto p-4 prose lg:prose-lg xl:prose-xl"), + H1(g.Text(`gomponents + HTMX`)), + P(g.Textf(`Time at last full page refresh was %v.`, now.Format(timeFormat))), + partial(now), + FormEl(Method("post"), Action("/"), hx.Boost("true"), hx.Target("#partial"), hx.Swap("outerHTML"), + Button(Type("submit"), g.Text(`Update time`), + Class("rounded-md border border-transparent bg-orange-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-orange-700 focus:outline-none focus:ring-2 focus:ring-orange-500 focus:ring-offset-2"), + ), + ), + ), + }, + }) +} + +func partial(now time.Time) g.Node { + return P(ID("partial"), g.Textf(`Time was last updated at %v.`, now.Format(timeFormat))) +} diff --git a/http/http_test.go b/http/http_test.go index 89837cd..68cc3d1 100644 --- a/http/http_test.go +++ b/http/http_test.go @@ -88,3 +88,9 @@ func ExampleIsBoosted() { } }) } + +func ExampleSetRefresh() { + _ = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + hxhttp.SetRefresh(w.Header()) + }) +}