feat: clicktoload

This commit is contained in:
joerdav 2023-04-19 10:55:03 +01:00
parent 60d3a869d2
commit 35b7c0cd28
No known key found for this signature in database
GPG Key ID: 7E93835EA5290C52
6 changed files with 618 additions and 4 deletions

41
clicktoload/handlers.go Normal file
View File

@ -0,0 +1,41 @@
package clicktoload
import (
"fmt"
"net/http"
"strconv"
"time"
"github.com/rs/xid"
)
type user struct {
name, email, id string
}
func Handlers(prefix string, mux *http.ServeMux) {
mux.HandleFunc(prefix+"/", index)
mux.HandleFunc(prefix+"/contacts/", getPage)
}
func index(w http.ResponseWriter, r *http.Request) {
// Load users
Index(getUsers(1)).Render(r.Context(), w)
}
func getPage(w http.ResponseWriter, r *http.Request) {
page, _ := strconv.Atoi(r.URL.Query().Get("page"))
tbody(getUsers(page), page).Render(r.Context(), w)
}
func getUsers(page int) []user {
var users []user
for i := 0; i < 10; i++ {
users = append(users, user{
"Agent Smith",
fmt.Sprintf("void%d@null.org", (page*10)+i),
xid.NewWithTime(time.Now()).String(),
})
}
return users
}

View File

@ -0,0 +1,52 @@
package clicktoload
import (
"fmt"
"examples/shared"
)
templ demo(users []user, page int) {
<table class="table"><thead>
<tr>
<td>Name</td>
<td>Email</td>
<td>ID</td>
</tr>
</thead><tbody>
@tbody(users, page)
</tbody></table>
}
templ tbody(users []user, page int) {
for _, u := range users {
<tr>
<td>{ u.name }</td>
<td>{ u.email }</td>
<td>{ u.id }</td>
</tr>
}
@replaceMe(page)
}
templ replaceMe(page int) {
<tr id="replaceMe">
<td colspan="3"><button class="button is-black" hx-get={ "/click-to-load/contacts/?page="+fmt.Sprint(page+1) } hx-target="#replaceMe" hx-swap="outerHTML">Load More Agents...</button></td>
</tr>
}
templ Index(users []user) {
@shared.Layout("Click to Load") {
<h2 class="title">Click to Load</h2>
<p>This example shows how to implement click-to-load the next page in a table of data. The crux of the demo is the final row:</p>
<pre><code class="language-html">
@shared.Raw() {
@replaceMe(1)
}
</code></pre>
<p>This row contains a button that will replace the entire row with the next page of results (which will contain a button to load the next page of results). And so on.</p>
<h2 class="title">Demo</h2>
@demo(users, 1)
}
}

View File

@ -0,0 +1,511 @@
// Code generated by templ@(devel) DO NOT EDIT.
package clicktoload
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import "context"
import "io"
import "bytes"
// GoExpression
import (
"fmt"
"examples/shared"
)
func demo(users []user, page int) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
templBuffer, templIsBuffer := w.(*bytes.Buffer)
if !templIsBuffer {
templBuffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templBuffer)
}
ctx = templ.InitializeContext(ctx)
var_1 := templ.GetChildren(ctx)
if var_1 == nil {
var_1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
// Element (standard)
_, err = templBuffer.WriteString("<table")
if err != nil {
return err
}
// Element Attributes
_, err = templBuffer.WriteString(" class=\"table\"")
if err != nil {
return err
}
_, err = templBuffer.WriteString(">")
if err != nil {
return err
}
// Element (standard)
_, err = templBuffer.WriteString("<thead>")
if err != nil {
return err
}
// Element (standard)
_, err = templBuffer.WriteString("<tr>")
if err != nil {
return err
}
// Element (standard)
_, err = templBuffer.WriteString("<td>")
if err != nil {
return err
}
// Text
var_2 := `Name`
_, err = templBuffer.WriteString(var_2)
if err != nil {
return err
}
_, err = templBuffer.WriteString("</td>")
if err != nil {
return err
}
// Element (standard)
_, err = templBuffer.WriteString("<td>")
if err != nil {
return err
}
// Text
var_3 := `Email`
_, err = templBuffer.WriteString(var_3)
if err != nil {
return err
}
_, err = templBuffer.WriteString("</td>")
if err != nil {
return err
}
// Element (standard)
_, err = templBuffer.WriteString("<td>")
if err != nil {
return err
}
// Text
var_4 := `ID`
_, err = templBuffer.WriteString(var_4)
if err != nil {
return err
}
_, err = templBuffer.WriteString("</td>")
if err != nil {
return err
}
_, err = templBuffer.WriteString("</tr>")
if err != nil {
return err
}
_, err = templBuffer.WriteString("</thead>")
if err != nil {
return err
}
// Element (standard)
_, err = templBuffer.WriteString("<tbody>")
if err != nil {
return err
}
// TemplElement
err = tbody(users, page).Render(ctx, templBuffer)
if err != nil {
return err
}
_, err = templBuffer.WriteString("</tbody>")
if err != nil {
return err
}
_, err = templBuffer.WriteString("</table>")
if err != nil {
return err
}
if !templIsBuffer {
_, err = io.Copy(w, templBuffer)
}
return err
})
}
func tbody(users []user, page int) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
templBuffer, templIsBuffer := w.(*bytes.Buffer)
if !templIsBuffer {
templBuffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templBuffer)
}
ctx = templ.InitializeContext(ctx)
var_5 := templ.GetChildren(ctx)
if var_5 == nil {
var_5 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
// For
for _, u := range users {
// Element (standard)
_, err = templBuffer.WriteString("<tr>")
if err != nil {
return err
}
// Element (standard)
_, err = templBuffer.WriteString("<td>")
if err != nil {
return err
}
// StringExpression
var var_6 string = u.name
_, err = templBuffer.WriteString(templ.EscapeString(var_6))
if err != nil {
return err
}
_, err = templBuffer.WriteString("</td>")
if err != nil {
return err
}
// Element (standard)
_, err = templBuffer.WriteString("<td>")
if err != nil {
return err
}
// StringExpression
var var_7 string = u.email
_, err = templBuffer.WriteString(templ.EscapeString(var_7))
if err != nil {
return err
}
_, err = templBuffer.WriteString("</td>")
if err != nil {
return err
}
// Element (standard)
_, err = templBuffer.WriteString("<td>")
if err != nil {
return err
}
// StringExpression
var var_8 string = u.id
_, err = templBuffer.WriteString(templ.EscapeString(var_8))
if err != nil {
return err
}
_, err = templBuffer.WriteString("</td>")
if err != nil {
return err
}
_, err = templBuffer.WriteString("</tr>")
if err != nil {
return err
}
}
// TemplElement
err = replaceMe(page).Render(ctx, templBuffer)
if err != nil {
return err
}
if !templIsBuffer {
_, err = io.Copy(w, templBuffer)
}
return err
})
}
func replaceMe(page int) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
templBuffer, templIsBuffer := w.(*bytes.Buffer)
if !templIsBuffer {
templBuffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templBuffer)
}
ctx = templ.InitializeContext(ctx)
var_9 := templ.GetChildren(ctx)
if var_9 == nil {
var_9 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
// Element (standard)
_, err = templBuffer.WriteString("<tr")
if err != nil {
return err
}
// Element Attributes
_, err = templBuffer.WriteString(" id=\"replaceMe\"")
if err != nil {
return err
}
_, err = templBuffer.WriteString(">")
if err != nil {
return err
}
// Element (standard)
_, err = templBuffer.WriteString("<td")
if err != nil {
return err
}
// Element Attributes
_, err = templBuffer.WriteString(" colspan=\"3\"")
if err != nil {
return err
}
_, err = templBuffer.WriteString(">")
if err != nil {
return err
}
// Element (standard)
_, err = templBuffer.WriteString("<button")
if err != nil {
return err
}
// Element Attributes
_, err = templBuffer.WriteString(" class=\"button is-black\"")
if err != nil {
return err
}
_, err = templBuffer.WriteString(" hx-get=")
if err != nil {
return err
}
_, err = templBuffer.WriteString("\"")
if err != nil {
return err
}
_, err = templBuffer.WriteString(templ.EscapeString("/click-to-load/contacts/?page="+fmt.Sprint(page+1)))
if err != nil {
return err
}
_, err = templBuffer.WriteString("\"")
if err != nil {
return err
}
_, err = templBuffer.WriteString(" hx-target=\"#replaceMe\"")
if err != nil {
return err
}
_, err = templBuffer.WriteString(" hx-swap=\"outerHTML\"")
if err != nil {
return err
}
_, err = templBuffer.WriteString(">")
if err != nil {
return err
}
// Text
var_10 := `Load More Agents...`
_, err = templBuffer.WriteString(var_10)
if err != nil {
return err
}
_, err = templBuffer.WriteString("</button>")
if err != nil {
return err
}
_, err = templBuffer.WriteString("</td>")
if err != nil {
return err
}
_, err = templBuffer.WriteString("</tr>")
if err != nil {
return err
}
if !templIsBuffer {
_, err = io.Copy(w, templBuffer)
}
return err
})
}
func Index(users []user) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
templBuffer, templIsBuffer := w.(*bytes.Buffer)
if !templIsBuffer {
templBuffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templBuffer)
}
ctx = templ.InitializeContext(ctx)
var_11 := templ.GetChildren(ctx)
if var_11 == nil {
var_11 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
// TemplElement
var_12 := templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
templBuffer, templIsBuffer := w.(*bytes.Buffer)
if !templIsBuffer {
templBuffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templBuffer)
}
// Element (standard)
_, err = templBuffer.WriteString("<h2")
if err != nil {
return err
}
// Element Attributes
_, err = templBuffer.WriteString(" class=\"title\"")
if err != nil {
return err
}
_, err = templBuffer.WriteString(">")
if err != nil {
return err
}
// Text
var_13 := `Click to Load`
_, err = templBuffer.WriteString(var_13)
if err != nil {
return err
}
_, err = templBuffer.WriteString("</h2>")
if err != nil {
return err
}
// Whitespace (normalised)
_, err = templBuffer.WriteString(` `)
if err != nil {
return err
}
// Element (standard)
_, err = templBuffer.WriteString("<p>")
if err != nil {
return err
}
// Text
var_14 := `This example shows how to implement click-to-load the next page in a table of data. The crux of the demo is the final row:`
_, err = templBuffer.WriteString(var_14)
if err != nil {
return err
}
_, err = templBuffer.WriteString("</p>")
if err != nil {
return err
}
// Whitespace (normalised)
_, err = templBuffer.WriteString(` `)
if err != nil {
return err
}
// Element (standard)
_, err = templBuffer.WriteString("<pre>")
if err != nil {
return err
}
// Element (standard)
_, err = templBuffer.WriteString("<code")
if err != nil {
return err
}
// Element Attributes
_, err = templBuffer.WriteString(" class=\"language-html\"")
if err != nil {
return err
}
_, err = templBuffer.WriteString(">")
if err != nil {
return err
}
// TemplElement
var_15 := templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
templBuffer, templIsBuffer := w.(*bytes.Buffer)
if !templIsBuffer {
templBuffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templBuffer)
}
// TemplElement
err = replaceMe(1).Render(ctx, templBuffer)
if err != nil {
return err
}
if !templIsBuffer {
_, err = io.Copy(w, templBuffer)
}
return err
})
err = shared.Raw().Render(templ.WithChildren(ctx, var_15), templBuffer)
if err != nil {
return err
}
_, err = templBuffer.WriteString("</code>")
if err != nil {
return err
}
_, err = templBuffer.WriteString("</pre>")
if err != nil {
return err
}
// Whitespace (normalised)
_, err = templBuffer.WriteString(` `)
if err != nil {
return err
}
// Element (standard)
_, err = templBuffer.WriteString("<p>")
if err != nil {
return err
}
// Text
var_16 := `This row contains a button that will replace the entire row with the next page of results (which will contain a button to load the next page of results). And so on.`
_, err = templBuffer.WriteString(var_16)
if err != nil {
return err
}
_, err = templBuffer.WriteString("</p>")
if err != nil {
return err
}
// Whitespace (normalised)
_, err = templBuffer.WriteString(` `)
if err != nil {
return err
}
// Element (standard)
_, err = templBuffer.WriteString("<h2")
if err != nil {
return err
}
// Element Attributes
_, err = templBuffer.WriteString(" class=\"title\"")
if err != nil {
return err
}
_, err = templBuffer.WriteString(">")
if err != nil {
return err
}
// Text
var_17 := `Demo`
_, err = templBuffer.WriteString(var_17)
if err != nil {
return err
}
_, err = templBuffer.WriteString("</h2>")
if err != nil {
return err
}
// Whitespace (normalised)
_, err = templBuffer.WriteString(` `)
if err != nil {
return err
}
// TemplElement
err = demo(users, 1).Render(ctx, templBuffer)
if err != nil {
return err
}
if !templIsBuffer {
_, err = io.Copy(w, templBuffer)
}
return err
})
err = shared.Layout("Click to Load").Render(templ.WithChildren(ctx, var_12), templBuffer)
if err != nil {
return err
}
if !templIsBuffer {
_, err = io.Copy(w, templBuffer)
}
return err
})
}

9
go.mod
View File

@ -2,9 +2,10 @@ module examples
go 1.21 go 1.21
require github.com/a-h/templ v0.2.234-0.20230416205859-20293271f3c5
require ( require (
github.com/yosssi/gohtml v0.0.0-20201013000340-ee4748c638f4 // indirect github.com/a-h/templ v0.2.234-0.20230416205859-20293271f3c5
golang.org/x/net v0.9.0 // indirect github.com/rs/xid v1.5.0
github.com/yosssi/gohtml v0.0.0-20201013000340-ee4748c638f4
) )
require golang.org/x/net v0.9.0 // indirect

2
go.sum
View File

@ -2,6 +2,8 @@ github.com/a-h/templ v0.2.233 h1:EnZqZmtV0YICqWG6MtLNmTcWuFkl2ImyQ63SIpWaM2Y=
github.com/a-h/templ v0.2.233/go.mod h1:h1DdzFMWVApvTcZBNmM6+mD6EPq6uYkncMNF7zdLj9I= github.com/a-h/templ v0.2.233/go.mod h1:h1DdzFMWVApvTcZBNmM6+mD6EPq6uYkncMNF7zdLj9I=
github.com/a-h/templ v0.2.234-0.20230416205859-20293271f3c5 h1:NeF/iw7KU9W7CYYJimd5x7ooOXCLrfo8FcHdFPUU+2w= github.com/a-h/templ v0.2.234-0.20230416205859-20293271f3c5 h1:NeF/iw7KU9W7CYYJimd5x7ooOXCLrfo8FcHdFPUU+2w=
github.com/a-h/templ v0.2.234-0.20230416205859-20293271f3c5/go.mod h1:nqma2qb9ViAJOP4MBucyH+SPbOyNDZaRQyusfpK4PjY= github.com/a-h/templ v0.2.234-0.20230416205859-20293271f3c5/go.mod h1:nqma2qb9ViAJOP4MBucyH+SPbOyNDZaRQyusfpK4PjY=
github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/yosssi/gohtml v0.0.0-20201013000340-ee4748c638f4 h1:0sw0nJM544SpsihWx1bkXdYLQDlzRflMgFJQ4Yih9ts= github.com/yosssi/gohtml v0.0.0-20201013000340-ee4748c638f4 h1:0sw0nJM544SpsihWx1bkXdYLQDlzRflMgFJQ4Yih9ts=
github.com/yosssi/gohtml v0.0.0-20201013000340-ee4748c638f4/go.mod h1:+ccdNT0xMY1dtc5XBxumbYfOUhmduiGudqaDgD2rVRE= github.com/yosssi/gohtml v0.0.0-20201013000340-ee4748c638f4/go.mod h1:+ccdNT0xMY1dtc5XBxumbYfOUhmduiGudqaDgD2rVRE=
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=

View File

@ -3,6 +3,7 @@ package main
import ( import (
"examples/bulkupdate" "examples/bulkupdate"
"examples/clicktoedit" "examples/clicktoedit"
"examples/clicktoload"
"log" "log"
"net/http" "net/http"
@ -44,4 +45,10 @@ var examples = []Example{
Slug: "bulk-update", Slug: "bulk-update",
Handlers: bulkupdate.Handlers, Handlers: bulkupdate.Handlers,
}, },
{
Name: "Click to Load",
Desc: "Demonstrates clicking to load more rows in a table",
Slug: "click-to-load",
Handlers: clicktoload.Handlers,
},
} }