diff --git a/go.mod b/go.mod
index 851cafb..c70bbe1 100644
--- a/go.mod
+++ b/go.mod
@@ -3,6 +3,7 @@ module examples
go 1.21
require (
+ github.com/a-h/pathvars v0.0.12
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
diff --git a/go.sum b/go.sum
index cad4968..fb3442e 100644
--- a/go.sum
+++ b/go.sum
@@ -1,3 +1,5 @@
+github.com/a-h/pathvars v0.0.12 h1:B4JaZGvHKNgNNlw8LMayPM/Hc0f3xZ2PXivu8YIl/X0=
+github.com/a-h/pathvars v0.0.12/go.mod h1:7rLTtvDVyKneR/N65hC0lh2sZ2KRyAmWFaOvv00uxb0=
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=
diff --git a/inlinevalidation/handlers.go b/inlinevalidation/handlers.go
new file mode 100644
index 0000000..ad6b88e
--- /dev/null
+++ b/inlinevalidation/handlers.go
@@ -0,0 +1,78 @@
+package inlinevalidation
+
+import (
+ "errors"
+ "net/http"
+
+ "github.com/a-h/pathvars"
+)
+
+var validateMatcher = pathvars.NewExtractor("/inline-validation/validate/{name}")
+
+func Handlers(prefix string, mux *http.ServeMux) {
+ mux.HandleFunc(prefix+"/", index)
+ mux.HandleFunc(prefix+"/validate/", validate)
+}
+
+func index(w http.ResponseWriter, r *http.Request) {
+ Index().Render(r.Context(), w)
+}
+
+func validate(w http.ResponseWriter, r *http.Request) {
+ vals, ok := validateMatcher.Extract(r.URL)
+ if !ok {
+ w.WriteHeader(500)
+ return
+ }
+ name, ok := vals["name"]
+ if !ok {
+ w.WriteHeader(500)
+ return
+ }
+ f, ok := fields[name]
+ if !ok {
+ w.WriteHeader(500)
+ return
+ }
+ if err := r.ParseForm(); err != nil {
+ w.WriteHeader(500)
+ return
+ }
+ val := r.FormValue(name)
+ inp(f, name, val, f.validator(val)).Render(r.Context(), w)
+}
+
+type field struct {
+ text string
+ validator func(string) error
+}
+
+var fields = map[string]field{
+ "email": {
+ text: "Email",
+ validator: func(value string) error {
+ if value != "test@test.com" {
+ return errors.New("Only test@test.com is valid.")
+ }
+ return nil
+ },
+ },
+ "firstName": {
+ text: "First Name",
+ validator: func(value string) error {
+ if value == "" {
+ return errors.New("Required")
+ }
+ return nil
+ },
+ },
+ "lastName": {
+ text: "Last Name",
+ validator: func(value string) error {
+ if value == "" {
+ return errors.New("Required")
+ }
+ return nil
+ },
+ },
+}
diff --git a/inlinevalidation/templates.templ b/inlinevalidation/templates.templ
new file mode 100644
index 0000000..c25dd6d
--- /dev/null
+++ b/inlinevalidation/templates.templ
@@ -0,0 +1,36 @@
+package inlinevalidation
+
+import "examples/shared"
+
+templ demo() {
+
+}
+
+templ inp(f field, name, value string, validation error) {
+
+
+
+ if validation != nil {
+
{ validation.Error() }
+ }
+
+}
+
+templ Index() {
+ @shared.Layout("Inline Validation") {
+ Inline Validation
+ @demo()
+ }
+}
+
diff --git a/inlinevalidation/templates_templ.go b/inlinevalidation/templates_templ.go
new file mode 100644
index 0000000..09d750c
--- /dev/null
+++ b/inlinevalidation/templates_templ.go
@@ -0,0 +1,381 @@
+// Code generated by templ@(devel) DO NOT EDIT.
+
+package inlinevalidation
+
+//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 "examples/shared"
+
+func demo() 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("")
+ if err != nil {
+ return err
+ }
+ if !templIsBuffer {
+ _, err = io.Copy(w, templBuffer)
+ }
+ return err
+ })
+}
+
+func inp(f field, name, value string, validation error) 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_3 := templ.GetChildren(ctx)
+ if var_3 == nil {
+ var_3 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ // Element (standard)
+ _, err = templBuffer.WriteString("")
+ if err != nil {
+ return err
+ }
+ // Element (standard)
+ _, err = templBuffer.WriteString("
")
+ if err != nil {
+ return err
+ }
+ // Element (standard)
+ _, err = templBuffer.WriteString("
")
+ if err != nil {
+ return err
+ }
+ // Element (void)
+ _, err = templBuffer.WriteString("")
+ if err != nil {
+ return err
+ }
+ _, err = templBuffer.WriteString("
")
+ if err != nil {
+ return err
+ }
+ // If
+ if validation != nil {
+ // Element (standard)
+ _, err = templBuffer.WriteString("
")
+ if err != nil {
+ return err
+ }
+ // StringExpression
+ var var_5 string = validation.Error()
+ _, err = templBuffer.WriteString(templ.EscapeString(var_5))
+ if err != nil {
+ return err
+ }
+ _, err = templBuffer.WriteString("
")
+ if err != nil {
+ return err
+ }
+ }
+ _, err = templBuffer.WriteString("
")
+ if err != nil {
+ return err
+ }
+ if !templIsBuffer {
+ _, err = io.Copy(w, templBuffer)
+ }
+ return err
+ })
+}
+
+func Index() 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_6 := templ.GetChildren(ctx)
+ if var_6 == nil {
+ var_6 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ // TemplElement
+ var_7 := 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("")
+ if err != nil {
+ return err
+ }
+ // Text
+ var_8 := `Inline Validation`
+ _, err = templBuffer.WriteString(var_8)
+ if err != nil {
+ return err
+ }
+ _, err = templBuffer.WriteString("
")
+ if err != nil {
+ return err
+ }
+ // Whitespace (normalised)
+ _, err = templBuffer.WriteString(` `)
+ if err != nil {
+ return err
+ }
+ // TemplElement
+ err = demo().Render(ctx, templBuffer)
+ if err != nil {
+ return err
+ }
+ if !templIsBuffer {
+ _, err = io.Copy(w, templBuffer)
+ }
+ return err
+ })
+ err = shared.Layout("Inline Validation").Render(templ.WithChildren(ctx, var_7), templBuffer)
+ if err != nil {
+ return err
+ }
+ if !templIsBuffer {
+ _, err = io.Copy(w, templBuffer)
+ }
+ return err
+ })
+}
+
diff --git a/main.go b/main.go
index 1b58493..cba1c90 100644
--- a/main.go
+++ b/main.go
@@ -6,6 +6,7 @@ import (
"examples/clicktoload"
"examples/deleterow"
"examples/editrow"
+ "examples/inlinevalidation"
"examples/lazyload"
"log"
"net/http"
@@ -72,4 +73,10 @@ var examples = []Example{
Slug: "lazy-loading",
Handlers: lazyload.Handlers,
},
+ {
+ Name: "Inline Validation",
+ Desc: "Demonstrates how to do inline field validation",
+ Slug: "inline-validation",
+ Handlers: inlinevalidation.Handlers,
+ },
}