add form validation
This commit is contained in:
parent
82f11b254b
commit
3f2cbcea33
8 changed files with 131 additions and 18 deletions
|
@ -20,8 +20,10 @@
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
<form action="/threads/{{.Thread.ID}}/{{.Post.ID}}" method="POST">
|
<form action="/threads/{{.Thread.ID}}/{{.Post.ID}}" method="POST">
|
||||||
{{.CSRF}}
|
{{.CSRF}}
|
||||||
<textarea name="content" class="form-control border-0 border-bottom-1 p-3"
|
<textarea name="content" class="form-control border-0 border-bottom-1 p-3 {{with .Form.Errors.Content}}is-invalid{{end}}"
|
||||||
placeholder="What are your thoughts?" rows="4"></textarea>
|
placeholder="What are your thoughts?" rows="4">
|
||||||
|
{{- with .Form.Content}}{{.}}{{end -}}
|
||||||
|
</textarea>
|
||||||
<div class="border-top p-1">
|
<div class="border-top p-1">
|
||||||
<button class="btn btn-primary btn-sm">Comment</button>
|
<button class="btn btn-primary btn-sm">Comment</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -9,12 +9,19 @@
|
||||||
{{.CSRF}}
|
{{.CSRF}}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>Title</label>
|
<label>Title</label>
|
||||||
<input name="title" type="text" class="form-control" placeholder="Give your post a great title">
|
<input name="title" type="text" class="form-control {{with .Form.Errors.Title}}is-invalid{{end}}" placeholder="Give your post a great title" value="{{with .Form.Title}}{{.}}{{end}}">
|
||||||
|
{{with .Form.Errors.Title}}
|
||||||
|
<div class="invalid-feedack">{{.}}</div>
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>Text</label>
|
<label>Text</label>
|
||||||
<textarea name="content" class="form-control" rows="3"
|
<textarea name="content" class="form-control {{with .Form.Errors.Content}}is-invalid{{end}}" rows="3" placeholder="Tell people about your thoughts">
|
||||||
placeholder="Tell people about your thoughts"></textarea>
|
{{- with .Form.Content}}{{.}}{{end -}}
|
||||||
|
</textarea>
|
||||||
|
{{with .Form.Errors.Content}}
|
||||||
|
<div class="invalid-feedack">{{.}}</div>
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-primary">Submit Post</button>
|
<button type="submit" class="btn btn-primary">Submit Post</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -7,12 +7,20 @@
|
||||||
{{.CSRF}}
|
{{.CSRF}}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>Title</label>
|
<label>Title</label>
|
||||||
<input name="title" type="text" class="form-control" placeholder="Give your thread a great title">
|
<input name="title" type="text" class="form-control {{with .Form.Errors.Title}}is-invalid{{end}}" placeholder="Give your thread a great title" value="{{with .Form.Title}}{{.}}{{end}}">
|
||||||
|
{{with .Form.Errors.Title}}
|
||||||
|
<div class="invalid-feedack">{{.}}</div>
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>Description</label>
|
<label>Description</label>
|
||||||
<textarea name="description" class="form-control" rows="3"
|
<textarea name="description" class="form-control {{with .Form.Errors.Description}}is-invalid{{end}}" rows="3"
|
||||||
placeholder="Tell people what your thread is about"></textarea>
|
placeholder="Tell people what your thread is about">
|
||||||
|
{{- with .Form.Description}}{{.}}{{end -}}
|
||||||
|
</textarea>
|
||||||
|
{{with .Form.Errors.Description}}
|
||||||
|
<div class="invalid-feedack">{{.}}</div>
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-primary">Create Thread</button>
|
<button type="submit" class="btn btn-primary">Create Thread</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -16,7 +16,15 @@ type CommentHandler struct {
|
||||||
|
|
||||||
func (h *CommentHandler) Store() http.HandlerFunc {
|
func (h *CommentHandler) Store() http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
content := r.FormValue("content")
|
form := CreateCommentForm{
|
||||||
|
Content: r.FormValue("content"),
|
||||||
|
}
|
||||||
|
if !form.Validate() {
|
||||||
|
h.sessions.Put(r.Context(), "form", form)
|
||||||
|
http.Redirect(w, r, r.Referer(), http.StatusFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
idStr := chi.URLParam(r, "postID")
|
idStr := chi.URLParam(r, "postID")
|
||||||
|
|
||||||
id, err := uuid.Parse(idStr)
|
id, err := uuid.Parse(idStr)
|
||||||
|
@ -28,7 +36,7 @@ func (h *CommentHandler) Store() http.HandlerFunc {
|
||||||
if err := h.store.CreateComment(&goddit.Comment{
|
if err := h.store.CreateComment(&goddit.Comment{
|
||||||
ID: uuid.New(),
|
ID: uuid.New(),
|
||||||
PostID: id,
|
PostID: id,
|
||||||
Content: content,
|
Content: form.Content,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
|
|
68
web/forms.go
Normal file
68
web/forms.go
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
package web
|
||||||
|
|
||||||
|
import "encoding/gob"
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
gob.Register(CreatePostForm{})
|
||||||
|
gob.Register(CreateThreadForm{})
|
||||||
|
gob.Register(CreateCommentForm{})
|
||||||
|
gob.Register(FormErrors{})
|
||||||
|
}
|
||||||
|
|
||||||
|
type FormErrors map[string]string
|
||||||
|
|
||||||
|
type CreatePostForm struct {
|
||||||
|
Title string
|
||||||
|
Content string
|
||||||
|
|
||||||
|
Errors FormErrors
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *CreatePostForm) Validate() bool {
|
||||||
|
f.Errors = FormErrors{}
|
||||||
|
|
||||||
|
if f.Title == "" {
|
||||||
|
f.Errors["Title"] = "Please enter a title!"
|
||||||
|
}
|
||||||
|
if f.Content == "" {
|
||||||
|
f.Errors["Content"] = "Please enter a text!"
|
||||||
|
}
|
||||||
|
|
||||||
|
return len(f.Errors) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreateThreadForm struct {
|
||||||
|
Title string
|
||||||
|
Description string
|
||||||
|
|
||||||
|
Errors FormErrors
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *CreateThreadForm) Validate() bool {
|
||||||
|
f.Errors = FormErrors{}
|
||||||
|
|
||||||
|
if f.Title == "" {
|
||||||
|
f.Errors["Title"] = "Please enter a title!"
|
||||||
|
}
|
||||||
|
if f.Description == "" {
|
||||||
|
f.Errors["Description"] = "Please enter a description!"
|
||||||
|
}
|
||||||
|
|
||||||
|
return len(f.Errors) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreateCommentForm struct {
|
||||||
|
Content string
|
||||||
|
|
||||||
|
Errors FormErrors
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *CreateCommentForm) Validate() bool {
|
||||||
|
f.Errors = FormErrors{}
|
||||||
|
|
||||||
|
if f.Content == "" {
|
||||||
|
f.Errors["Content"] = "Please enter a comment!"
|
||||||
|
}
|
||||||
|
|
||||||
|
return len(f.Errors) == 0
|
||||||
|
}
|
|
@ -102,8 +102,15 @@ func (h *PostHandler) Show() http.HandlerFunc {
|
||||||
|
|
||||||
func (h *PostHandler) Store() http.HandlerFunc {
|
func (h *PostHandler) Store() http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
title := r.FormValue("title")
|
form := CreatePostForm{
|
||||||
content := r.FormValue("content")
|
Title: r.FormValue("title"),
|
||||||
|
Content: r.FormValue("content"),
|
||||||
|
}
|
||||||
|
if !form.Validate() {
|
||||||
|
h.sessions.Put(r.Context(), "form", form)
|
||||||
|
http.Redirect(w, r, r.Referer(), http.StatusFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
idStr := chi.URLParam(r, "id")
|
idStr := chi.URLParam(r, "id")
|
||||||
|
|
||||||
|
@ -122,8 +129,8 @@ func (h *PostHandler) Store() http.HandlerFunc {
|
||||||
p := &goddit.Post{
|
p := &goddit.Post{
|
||||||
ID: uuid.New(),
|
ID: uuid.New(),
|
||||||
ThreadID: t.ID,
|
ThreadID: t.ID,
|
||||||
Title: title,
|
Title: form.Title,
|
||||||
Content: content,
|
Content: form.Content,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := h.store.CreatePost(p); err != nil {
|
if err := h.store.CreatePost(p); err != nil {
|
||||||
|
|
|
@ -22,6 +22,7 @@ func NewSessionsManager(dataSourceName string) (*scs.SessionManager, error) {
|
||||||
|
|
||||||
type SessionData struct {
|
type SessionData struct {
|
||||||
FlashMessage string
|
FlashMessage string
|
||||||
|
Form interface{}
|
||||||
// UserID uuid.UUID
|
// UserID uuid.UUID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,5 +32,10 @@ func GetSessionData(session *scs.SessionManager, ctx context.Context) SessionDat
|
||||||
data.FlashMessage = session.PopString(ctx, "flash")
|
data.FlashMessage = session.PopString(ctx, "flash")
|
||||||
// data.UserID, _ = session.Get(ctx "user_id").(uuid.UUID)
|
// data.UserID, _ = session.Get(ctx "user_id").(uuid.UUID)
|
||||||
|
|
||||||
|
data.Form = session.Pop(ctx, "form")
|
||||||
|
if data.Form == nil {
|
||||||
|
data.Form = map[string]string{}
|
||||||
|
}
|
||||||
|
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,13 +91,20 @@ func (h *ThreadHandler) Show() http.HandlerFunc {
|
||||||
|
|
||||||
func (h *ThreadHandler) Store() http.HandlerFunc {
|
func (h *ThreadHandler) Store() http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
title := r.FormValue("title")
|
form := CreateThreadForm{
|
||||||
description := r.FormValue("description")
|
Title: r.FormValue("title"),
|
||||||
|
Description: r.FormValue("description"),
|
||||||
|
}
|
||||||
|
if !form.Validate() {
|
||||||
|
h.sessions.Put(r.Context(), "form", form)
|
||||||
|
http.Redirect(w, r, r.Referer(), http.StatusFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if err := h.store.CreateThread(&goddit.Thread{
|
if err := h.store.CreateThread(&goddit.Thread{
|
||||||
ID: uuid.New(),
|
ID: uuid.New(),
|
||||||
Title: title,
|
Title: form.Title,
|
||||||
Description: description,
|
Description: form.Description,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
|
|
Reference in a new issue