Compare commits

..

2 Commits

Author SHA1 Message Date
0ce91b983f Convert contact page to Templ 2024-07-14 19:51:02 -07:00
93205c7d00 Convert auth pages to Templ 2024-07-14 19:51:02 -07:00
12 changed files with 345 additions and 131 deletions

View File

@ -3,12 +3,15 @@ package handlers
import ( import (
"fmt" "fmt"
"github.com/a-h/templ"
"github.com/go-playground/validator/v10" "github.com/go-playground/validator/v10"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
"git.grosinger.net/tgrosinger/saasitone/pkg/form" "git.grosinger.net/tgrosinger/saasitone/pkg/form"
"git.grosinger.net/tgrosinger/saasitone/pkg/page" "git.grosinger.net/tgrosinger/saasitone/pkg/page"
"git.grosinger.net/tgrosinger/saasitone/pkg/services" "git.grosinger.net/tgrosinger/saasitone/pkg/services"
"git.grosinger.net/tgrosinger/saasitone/templ/layouts"
"git.grosinger.net/tgrosinger/saasitone/templ/pages"
"git.grosinger.net/tgrosinger/saasitone/templates" "git.grosinger.net/tgrosinger/saasitone/templates"
) )
@ -22,13 +25,6 @@ type (
mail *services.MailClient mail *services.MailClient
*services.TemplateRenderer *services.TemplateRenderer
} }
contactForm struct {
Email string `form:"email" validate:"required,email"`
Department string `form:"department" validate:"required,oneof=sales marketing hr"`
Message string `form:"message" validate:"required"`
form.Submission
}
) )
func init() { func init() {
@ -48,16 +44,22 @@ func (h *Contact) Routes(g *echo.Group) {
func (h *Contact) Page(ctx echo.Context) error { func (h *Contact) Page(ctx echo.Context) error {
p := page.New(ctx) p := page.New(ctx)
p.Layout = templates.LayoutMain
p.Name = templates.PageContact p.Name = templates.PageContact
p.Title = "Contact us" p.Title = "Contact us"
p.Form = form.Get[contactForm](ctx)
return h.RenderPage(ctx, p) f := form.Get[pages.ContactForm](ctx)
component := pages.Contact(p, f)
// TODO: This can be reused
p.LayoutComponent = func(content templ.Component) templ.Component {
return layouts.Main(p, content)
}
return h.RenderPageTempl(ctx, p, component)
} }
func (h *Contact) Submit(ctx echo.Context) error { func (h *Contact) Submit(ctx echo.Context) error {
var input contactForm var input pages.ContactForm
err := form.Submit(ctx, &input) err := form.Submit(ctx, &input)

74
templ/pages/contact.templ Normal file
View File

@ -0,0 +1,74 @@
package pages
import (
"git.grosinger.net/tgrosinger/saasitone/templ/components"
"git.grosinger.net/tgrosinger/saasitone/pkg/form"
"git.grosinger.net/tgrosinger/saasitone/pkg/page"
)
type ContactForm struct {
Email string `form:"email" validate:"required,email"`
Department string `form:"department" validate:"required,oneof=sales marketing hr"`
Message string `form:"message" validate:"required"`
form.Submission
}
templ Contact(p page.Page, f *ContactForm) {
if p.HTMX.Request.Target != "contact" {
<article class="message is-link">
<div class="message-body">
<p>This is an example of a form with inline, server-side validation and HTMX-powered AJAX submissions without writing a single line of JavaScript.</p>
<p>Only the form below will update async upon submission.</p>
</div>
</article>
}
if f.IsDone() {
<article class="message is-large is-success">
<div class="message-header">
<p>Thank you!</p>
</div>
<div class="message-body">
No email was actually sent but this entire operation was handled server-side and degrades without JavaScript enabled.
</div>
</article>
} else {
<form id="contact" method="post" hx-post={ p.ToURL("contact.submit") }>
<div class="field">
<label for="email" class="label">Email address</label>
<div class="control">
<input id="email" name="email" type="email" class={ "input", f.Submission.GetFieldStatusClass("Email") } value={ f.Email }/>
</div>
@components.FieldErrors(f.Submission.GetFieldErrors("Email"))
</div>
<div class="control">
<label class="label">Department</label>
<label class="radio">
<input type="radio" name="department" value="sales" checked?={ f.Department == "sales" }/>
Sales
</label>
<label class="radio">
<input type="radio" name="department" value="marketing" checked?={ f.Department == "marketing" }/>
Marketing
</label>
<label class="radio">
<input type="radio" name="department" value="hr" checked?={ f.Department == "hr" }/>
HR
</label>
@components.FieldErrors(f.Submission.GetFieldErrors("Department"))
</div>
<div class="field">
<label for="message" class="label">Message</label>
<div class="control">
<textarea id="message" name="message" class={ "textarea", f.Submission.GetFieldStatusClass("Message") }>{ f.Message }</textarea>
</div>
@components.FieldErrors(f.Submission.GetFieldErrors("Message"))
</div>
<div class="field is-grouped">
<div class="control">
<button class="button is-link">Submit</button>
</div>
</div>
@components.CSRF(p.CSRF)
</form>
}
}

View File

@ -0,0 +1,206 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.2.707
package pages
//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"
import (
"git.grosinger.net/tgrosinger/saasitone/pkg/form"
"git.grosinger.net/tgrosinger/saasitone/pkg/page"
"git.grosinger.net/tgrosinger/saasitone/templ/components"
)
type ContactForm struct {
Email string `form:"email" validate:"required,email"`
Department string `form:"department" validate:"required,oneof=sales marketing hr"`
Message string `form:"message" validate:"required"`
form.Submission
}
func Contact(p page.Page, f *ContactForm) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
if !templ_7745c5c3_IsBuffer {
templ_7745c5c3_Buffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
if p.HTMX.Request.Target != "contact" {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<article class=\"message is-link\"><div class=\"message-body\"><p>This is an example of a form with inline, server-side validation and HTMX-powered AJAX submissions without writing a single line of JavaScript.</p><p>Only the form below will update async upon submission.</p></div></article>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
if f.IsDone() {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<article class=\"message is-large is-success\"><div class=\"message-header\"><p>Thank you!</p></div><div class=\"message-body\">No email was actually sent but this entire operation was handled server-side and degrades without JavaScript enabled.</div></article>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<form id=\"contact\" method=\"post\" hx-post=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(p.ToURL("contact.submit"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templ/pages/contact.templ`, Line: 35, Col: 70}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><div class=\"field\"><label for=\"email\" class=\"label\">Email address</label><div class=\"control\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 = []any{"input", f.Submission.GetFieldStatusClass("Email")}
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var3...)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<input id=\"email\" name=\"email\" type=\"email\" class=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var3).String())
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templ/pages/contact.templ`, Line: 1, Col: 0}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(f.Email)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templ/pages/contact.templ`, Line: 39, Col: 125}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = components.FieldErrors(f.Submission.GetFieldErrors("Email")).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><div class=\"control\"><label class=\"label\">Department</label> <label class=\"radio\"><input type=\"radio\" name=\"department\" value=\"sales\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if f.Department == "sales" {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" checked")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("> Sales</label> <label class=\"radio\"><input type=\"radio\" name=\"department\" value=\"marketing\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if f.Department == "marketing" {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" checked")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("> Marketing</label> <label class=\"radio\"><input type=\"radio\" name=\"department\" value=\"hr\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if f.Department == "hr" {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" checked")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("> HR</label>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = components.FieldErrors(f.Submission.GetFieldErrors("Department")).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><div class=\"field\"><label for=\"message\" class=\"label\">Message</label><div class=\"control\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var6 = []any{"textarea", f.Submission.GetFieldStatusClass("Message")}
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var6...)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<textarea id=\"message\" name=\"message\" class=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var7 string
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var6).String())
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templ/pages/contact.templ`, Line: 1, Col: 0}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(f.Message)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templ/pages/contact.templ`, Line: 62, Col: 120}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</textarea></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = components.FieldErrors(f.Submission.GetFieldErrors("Message")).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><div class=\"field is-grouped\"><div class=\"control\"><button class=\"button is-link\">Submit</button></div></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = components.CSRF(p.CSRF).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</form>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
if !templ_7745c5c3_IsBuffer {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
}
return templ_7745c5c3_Err
})
}

View File

@ -11,7 +11,7 @@ type ForgotPasswordForm struct {
form.Submission form.Submission
} }
templ ForgotPassword(p page.Page, form *ForgotPasswordForm) { templ ForgotPassword(p page.Page, f *ForgotPasswordForm) {
<form method="post" hx-boost="true" action={ templ.URL(p.ToURL("forgot_password.submit")) }> <form method="post" hx-boost="true" action={ templ.URL(p.ToURL("forgot_password.submit")) }>
<div class="content"> <div class="content">
<p>Enter your email address and we'll email you a link that allows you to reset your password.</p> <p>Enter your email address and we'll email you a link that allows you to reset your password.</p>
@ -19,8 +19,8 @@ templ ForgotPassword(p page.Page, form *ForgotPasswordForm) {
<div class="field"> <div class="field">
<label for="email" class="label">Email address</label> <label for="email" class="label">Email address</label>
<div class="control"> <div class="control">
<input id="email" type="email" name="email" class={ "input", form.Submission.GetFieldStatusClass("Email") } value={ form.Email }/> <input id="email" type="email" name="email" class={ "input", f.Submission.GetFieldStatusClass("Email") } value={ f.Email }/>
@components.FieldErrors(form.Submission.GetFieldErrors("Email")) @components.FieldErrors(f.Submission.GetFieldErrors("Email"))
</div> </div>
</div> </div>
<div class="field is-grouped"> <div class="field is-grouped">

View File

@ -21,7 +21,7 @@ type ForgotPasswordForm struct {
form.Submission form.Submission
} }
func ForgotPassword(p page.Page, form *ForgotPasswordForm) templ.Component { func ForgotPassword(p page.Page, f *ForgotPasswordForm) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
if !templ_7745c5c3_IsBuffer { if !templ_7745c5c3_IsBuffer {
@ -47,7 +47,7 @@ func ForgotPassword(p page.Page, form *ForgotPasswordForm) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var3 = []any{"input", form.Submission.GetFieldStatusClass("Email")} var templ_7745c5c3_Var3 = []any{"input", f.Submission.GetFieldStatusClass("Email")}
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var3...) templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var3...)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
@ -70,9 +70,9 @@ func ForgotPassword(p page.Page, form *ForgotPasswordForm) templ.Component {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var5 string var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(form.Email) templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(f.Email)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templ/pages/forgot-password.templ`, Line: 22, Col: 130} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templ/pages/forgot-password.templ`, Line: 22, Col: 124}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -82,7 +82,7 @@ func ForgotPassword(p page.Page, form *ForgotPasswordForm) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = components.FieldErrors(form.Submission.GetFieldErrors("Email")).Render(ctx, templ_7745c5c3_Buffer) templ_7745c5c3_Err = components.FieldErrors(f.Submission.GetFieldErrors("Email")).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }

View File

@ -12,21 +12,21 @@ type LoginForm struct {
form.Submission form.Submission
} }
templ Login(p page.Page, form *LoginForm) { templ Login(p page.Page, f *LoginForm) {
<form method="post" hx-boost="true" action={ templ.URL(p.ToURL("login.submit")) }> <form method="post" hx-boost="true" action={ templ.URL(p.ToURL("login.submit")) }>
@components.Messages(p) @components.Messages(p)
<div class="field"> <div class="field">
<label for="email" class="label">Email address</label> <label for="email" class="label">Email address</label>
<div class="control"> <div class="control">
<input id="email" type="email" name="email" class={ "input", form.Submission.GetFieldStatusClass("Email") } value={ form.Email }/> <input id="email" type="email" name="email" class={ "input", f.Submission.GetFieldStatusClass("Email") } value={ f.Email }/>
@components.FieldErrors(form.Submission.GetFieldErrors("Email")) @components.FieldErrors(f.Submission.GetFieldErrors("Email"))
</div> </div>
</div> </div>
<div class="field"> <div class="field">
<label for="password" class="label">Password</label> <label for="password" class="label">Password</label>
<div class="control"> <div class="control">
<input id="password" type="password" name="password" placeholder="*******" class={ "input", form.Submission.GetFieldStatusClass("Password") }/> <input id="password" type="password" name="password" placeholder="*******" class={ "input", f.Submission.GetFieldStatusClass("Password") }/>
@components.FieldErrors(form.Submission.GetFieldErrors("Password")) @components.FieldErrors(f.Submission.GetFieldErrors("Password"))
</div> </div>
</div> </div>
<div class="field is-grouped"> <div class="field is-grouped">

View File

@ -22,7 +22,7 @@ type LoginForm struct {
form.Submission form.Submission
} }
func Login(p page.Page, form *LoginForm) templ.Component { func Login(p page.Page, f *LoginForm) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
if !templ_7745c5c3_IsBuffer { if !templ_7745c5c3_IsBuffer {
@ -56,7 +56,7 @@ func Login(p page.Page, form *LoginForm) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var3 = []any{"input", form.Submission.GetFieldStatusClass("Email")} var templ_7745c5c3_Var3 = []any{"input", f.Submission.GetFieldStatusClass("Email")}
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var3...) templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var3...)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
@ -79,9 +79,9 @@ func Login(p page.Page, form *LoginForm) templ.Component {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var5 string var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(form.Email) templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(f.Email)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templ/pages/login.templ`, Line: 21, Col: 130} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templ/pages/login.templ`, Line: 21, Col: 124}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -91,7 +91,7 @@ func Login(p page.Page, form *LoginForm) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = components.FieldErrors(form.Submission.GetFieldErrors("Email")).Render(ctx, templ_7745c5c3_Buffer) templ_7745c5c3_Err = components.FieldErrors(f.Submission.GetFieldErrors("Email")).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -99,7 +99,7 @@ func Login(p page.Page, form *LoginForm) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var6 = []any{"input", form.Submission.GetFieldStatusClass("Password")} var templ_7745c5c3_Var6 = []any{"input", f.Submission.GetFieldStatusClass("Password")}
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var6...) templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var6...)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
@ -121,7 +121,7 @@ func Login(p page.Page, form *LoginForm) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = components.FieldErrors(form.Submission.GetFieldErrors("Password")).Render(ctx, templ_7745c5c3_Buffer) templ_7745c5c3_Err = components.FieldErrors(f.Submission.GetFieldErrors("Password")).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }

View File

@ -14,34 +14,34 @@ type RegisterForm struct {
form.Submission form.Submission
} }
templ Register(p page.Page, form *RegisterForm) { templ Register(p page.Page, f *RegisterForm) {
<form method="post" hx-boost="true" action={ templ.URL(p.ToURL("register.submit")) }> <form method="post" hx-boost="true" action={ templ.URL(p.ToURL("register.submit")) }>
<div class="field"> <div class="field">
<label for="name" class="label">Name</label> <label for="name" class="label">Name</label>
<div class="control"> <div class="control">
<input type="text" id="name" name="name" class={ "input", form.Submission.GetFieldStatusClass("Name") } value={ form.Name }/> <input type="text" id="name" name="name" class={ "input", f.Submission.GetFieldStatusClass("Name") } value={ f.Name }/>
@components.FieldErrors(form.Submission.GetFieldErrors("Name")) @components.FieldErrors(f.Submission.GetFieldErrors("Name"))
</div> </div>
</div> </div>
<div class="field"> <div class="field">
<label for="email" class="label">Email address</label> <label for="email" class="label">Email address</label>
<div class="control"> <div class="control">
<input type="email" id="email" name="email" class={ "input", form.Submission.GetFieldStatusClass("Email") } value={ form.Email }/> <input type="email" id="email" name="email" class={ "input", f.Submission.GetFieldStatusClass("Email") } value={ f.Email }/>
@components.FieldErrors(form.Submission.GetFieldErrors("Email")) @components.FieldErrors(f.Submission.GetFieldErrors("Email"))
</div> </div>
</div> </div>
<div class="field"> <div class="field">
<label for="password" class="label">Password</label> <label for="password" class="label">Password</label>
<div class="control"> <div class="control">
<input type="password" id="password" name="password" placeholder="*******" class={ "input", form.Submission.GetFieldStatusClass("Password") }/> <input type="password" id="password" name="password" placeholder="*******" class={ "input", f.Submission.GetFieldStatusClass("Password") }/>
@components.FieldErrors(form.Submission.GetFieldErrors("Password")) @components.FieldErrors(f.Submission.GetFieldErrors("Password"))
</div> </div>
</div> </div>
<div class="field"> <div class="field">
<label for="password-confirm" class="label">Confirm password</label> <label for="password-confirm" class="label">Confirm password</label>
<div class="control"> <div class="control">
<input type="password" id="password-confirm" name="password-confirm" placeholder="*******" class={ "input", form.Submission.GetFieldStatusClass("ConfigmPassword") }/> <input type="password" id="password-confirm" name="password-confirm" placeholder="*******" class={ "input", f.Submission.GetFieldStatusClass("ConfigmPassword") }/>
@components.FieldErrors(form.Submission.GetFieldErrors("ConfigmPassword")) @components.FieldErrors(f.Submission.GetFieldErrors("ConfigmPassword"))
</div> </div>
</div> </div>
<div class="field is-grouped"> <div class="field is-grouped">

View File

@ -24,7 +24,7 @@ type RegisterForm struct {
form.Submission form.Submission
} }
func Register(p page.Page, form *RegisterForm) templ.Component { func Register(p page.Page, f *RegisterForm) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
if !templ_7745c5c3_IsBuffer { if !templ_7745c5c3_IsBuffer {
@ -50,7 +50,7 @@ func Register(p page.Page, form *RegisterForm) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var3 = []any{"input", form.Submission.GetFieldStatusClass("Name")} var templ_7745c5c3_Var3 = []any{"input", f.Submission.GetFieldStatusClass("Name")}
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var3...) templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var3...)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
@ -73,9 +73,9 @@ func Register(p page.Page, form *RegisterForm) templ.Component {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var5 string var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(form.Name) templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(f.Name)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templ/pages/register.templ`, Line: 22, Col: 125} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templ/pages/register.templ`, Line: 22, Col: 119}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -85,7 +85,7 @@ func Register(p page.Page, form *RegisterForm) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = components.FieldErrors(form.Submission.GetFieldErrors("Name")).Render(ctx, templ_7745c5c3_Buffer) templ_7745c5c3_Err = components.FieldErrors(f.Submission.GetFieldErrors("Name")).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -93,7 +93,7 @@ func Register(p page.Page, form *RegisterForm) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var6 = []any{"input", form.Submission.GetFieldStatusClass("Email")} var templ_7745c5c3_Var6 = []any{"input", f.Submission.GetFieldStatusClass("Email")}
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var6...) templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var6...)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
@ -116,9 +116,9 @@ func Register(p page.Page, form *RegisterForm) templ.Component {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var8 string var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(form.Email) templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(f.Email)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templ/pages/register.templ`, Line: 29, Col: 130} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templ/pages/register.templ`, Line: 29, Col: 124}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -128,7 +128,7 @@ func Register(p page.Page, form *RegisterForm) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = components.FieldErrors(form.Submission.GetFieldErrors("Email")).Render(ctx, templ_7745c5c3_Buffer) templ_7745c5c3_Err = components.FieldErrors(f.Submission.GetFieldErrors("Email")).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -136,7 +136,7 @@ func Register(p page.Page, form *RegisterForm) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var9 = []any{"input", form.Submission.GetFieldStatusClass("Password")} var templ_7745c5c3_Var9 = []any{"input", f.Submission.GetFieldStatusClass("Password")}
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var9...) templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var9...)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
@ -158,7 +158,7 @@ func Register(p page.Page, form *RegisterForm) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = components.FieldErrors(form.Submission.GetFieldErrors("Password")).Render(ctx, templ_7745c5c3_Buffer) templ_7745c5c3_Err = components.FieldErrors(f.Submission.GetFieldErrors("Password")).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -166,7 +166,7 @@ func Register(p page.Page, form *RegisterForm) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var11 = []any{"input", form.Submission.GetFieldStatusClass("ConfigmPassword")} var templ_7745c5c3_Var11 = []any{"input", f.Submission.GetFieldStatusClass("ConfigmPassword")}
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var11...) templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var11...)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
@ -188,7 +188,7 @@ func Register(p page.Page, form *RegisterForm) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = components.FieldErrors(form.Submission.GetFieldErrors("ConfigmPassword")).Render(ctx, templ_7745c5c3_Buffer) templ_7745c5c3_Err = components.FieldErrors(f.Submission.GetFieldErrors("ConfigmPassword")).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }

View File

@ -12,20 +12,20 @@ type ResetPasswordForm struct {
form.Submission form.Submission
} }
templ ResetPassword(p page.Page, form *ResetPasswordForm) { templ ResetPassword(p page.Page, f *ResetPasswordForm) {
<form method="post" hx-boost="true" action={ templ.URL(p.Path) }> <form method="post" hx-boost="true" action={ templ.URL(p.Path) }>
<div class="field"> <div class="field">
<label for="password" class="label">Password</label> <label for="password" class="label">Password</label>
<div class="control"> <div class="control">
<input type="password" id="password" name="password" placeholder="*******" class={ "input", form.Submission.GetFieldStatusClass("Password") }/> <input type="password" id="password" name="password" placeholder="*******" class={ "input", f.Submission.GetFieldStatusClass("Password") }/>
@components.FieldErrors(form.Submission.GetFieldErrors("Password")) @components.FieldErrors(f.Submission.GetFieldErrors("Password"))
</div> </div>
</div> </div>
<div class="field"> <div class="field">
<label for="password-confirm" class="label">Confirm password</label> <label for="password-confirm" class="label">Confirm password</label>
<div class="control"> <div class="control">
<input type="password" id="password-confirm" name="password-confirm" placeholder="*******" class={ "input", form.Submission.GetFieldStatusClass("ConfirmPassword") }/> <input type="password" id="password-confirm" name="password-confirm" placeholder="*******" class={ "input", f.Submission.GetFieldStatusClass("ConfirmPassword") }/>
@components.FieldErrors(form.Submission.GetFieldErrors("ConfigmPassword")) @components.FieldErrors(f.Submission.GetFieldErrors("ConfigmPassword"))
</div> </div>
</div> </div>
<div class="field is-grouped"> <div class="field is-grouped">

View File

@ -22,7 +22,7 @@ type ResetPasswordForm struct {
form.Submission form.Submission
} }
func ResetPassword(p page.Page, form *ResetPasswordForm) templ.Component { func ResetPassword(p page.Page, f *ResetPasswordForm) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
if !templ_7745c5c3_IsBuffer { if !templ_7745c5c3_IsBuffer {
@ -48,7 +48,7 @@ func ResetPassword(p page.Page, form *ResetPasswordForm) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var3 = []any{"input", form.Submission.GetFieldStatusClass("Password")} var templ_7745c5c3_Var3 = []any{"input", f.Submission.GetFieldStatusClass("Password")}
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var3...) templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var3...)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
@ -70,7 +70,7 @@ func ResetPassword(p page.Page, form *ResetPasswordForm) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = components.FieldErrors(form.Submission.GetFieldErrors("Password")).Render(ctx, templ_7745c5c3_Buffer) templ_7745c5c3_Err = components.FieldErrors(f.Submission.GetFieldErrors("Password")).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -78,7 +78,7 @@ func ResetPassword(p page.Page, form *ResetPasswordForm) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var5 = []any{"input", form.Submission.GetFieldStatusClass("ConfirmPassword")} var templ_7745c5c3_Var5 = []any{"input", f.Submission.GetFieldStatusClass("ConfirmPassword")}
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var5...) templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var5...)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
@ -100,7 +100,7 @@ func ResetPassword(p page.Page, form *ResetPasswordForm) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = components.FieldErrors(form.Submission.GetFieldErrors("ConfigmPassword")).Render(ctx, templ_7745c5c3_Buffer) templ_7745c5c3_Err = components.FieldErrors(f.Submission.GetFieldErrors("ConfigmPassword")).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }

View File

@ -1,68 +0,0 @@
{{define "content"}}
{{- if not (eq .HTMX.Request.Target "contact")}}
<article class="message is-link">
<div class="message-body">
<p>This is an example of a form with inline, server-side validation and HTMX-powered AJAX submissions without writing a single line of JavaScript.</p>
<p>Only the form below will update async upon submission.</p>
</div>
</article>
{{- end}}
{{template "form" .}}
{{end}}
{{define "form"}}
{{- if .Form.IsDone}}
<article class="message is-large is-success">
<div class="message-header">
<p>Thank you!</p>
</div>
<div class="message-body">
No email was actually sent but this entire operation was handled server-side and degrades without JavaScript enabled.
</div>
</article>
{{- else}}
<form id="contact" method="post" hx-post="{{url "contact.submit"}}">
<div class="field">
<label for="email" class="label">Email address</label>
<div class="control">
<input id="email" name="email" type="email" class="input {{.Form.GetFieldStatusClass "Email"}}" value="{{.Form.Email}}">
</div>
{{template "field-errors" (.Form.GetFieldErrors "Email")}}
</div>
<div class="control">
<label class="label">Department</label>
<label class="radio">
<input type="radio" name="department" value="sales" {{if eq .Form.Department "sales"}}checked{{end}}/>
Sales
</label>
<label class="radio">
<input type="radio" name="department" value="marketing" {{if eq .Form.Department "marketing"}}checked{{end}}/>
Marketing
</label>
<label class="radio">
<input type="radio" name="department" value="hr" {{if eq .Form.Department "hr"}}checked{{end}}/>
HR
</label>
{{template "field-errors" (.Form.GetFieldErrors "Department")}}
</div>
<div class="field">
<label for="message" class="label">Message</label>
<div class="control">
<textarea id="message" name="message" class="textarea {{.Form.GetFieldStatusClass "Message"}}">{{.Form.Message}}</textarea>
</div>
{{template "field-errors" (.Form.GetFieldErrors "Message")}}
</div>
<div class="field is-grouped">
<div class="control">
<button class="button is-link">Submit</button>
</div>
</div>
{{template "csrf" .}}
</form>
{{- end}}
{{end}}