feat: clicktoload
This commit is contained in:
parent
60d3a869d2
commit
35b7c0cd28
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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
9
go.mod
|
@ -2,9 +2,10 @@ module examples
|
|||
|
||||
go 1.21
|
||||
|
||||
require github.com/a-h/templ v0.2.234-0.20230416205859-20293271f3c5
|
||||
|
||||
require (
|
||||
github.com/yosssi/gohtml v0.0.0-20201013000340-ee4748c638f4 // indirect
|
||||
golang.org/x/net v0.9.0 // indirect
|
||||
github.com/a-h/templ v0.2.234-0.20230416205859-20293271f3c5
|
||||
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
2
go.sum
|
@ -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.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/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/go.mod h1:+ccdNT0xMY1dtc5XBxumbYfOUhmduiGudqaDgD2rVRE=
|
||||
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
|
||||
|
|
7
main.go
7
main.go
|
@ -3,6 +3,7 @@ package main
|
|||
import (
|
||||
"examples/bulkupdate"
|
||||
"examples/clicktoedit"
|
||||
"examples/clicktoload"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
|
@ -44,4 +45,10 @@ var examples = []Example{
|
|||
Slug: "bulk-update",
|
||||
Handlers: bulkupdate.Handlers,
|
||||
},
|
||||
{
|
||||
Name: "Click to Load",
|
||||
Desc: "Demonstrates clicking to load more rows in a table",
|
||||
Slug: "click-to-load",
|
||||
Handlers: clicktoload.Handlers,
|
||||
},
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue