gobuffalo/buffalo

Validation errors do not show up in HTML

Closed this issue · 3 comments

  • Check the documentation resources gobuffalo.io and godoc.org to see if there are docs, examples, etc. that might solve your problem quicker.
  • Make sure to provide as much information as possible (stack traces, error logs, code examples, screenshots...), so we can better help you.

Description

If this is a feature request, explain why it should be added. Specific use-cases are best.

For bug reports, please provide as much relevant info as possible.

Steps to Reproduce the Problem

  1. buffalo new app
  2. cd app
  3. buffalo generate resource message
  4. Fix template according to gobuffalo/cli#55 (comment)
  5. Add a field Text to the model
  6. Add an input tag to the form
  7. Add a validation
  8. Run the app
  9. Navigate to http://localhost:3000/messages/
  10. Enter wrong data and press "Save"

The diff below shows the changes made after step 4.

diff --git a/migrations/20211126154047_create_messages.up.fizz b/migrations/20211126154047_create_messages.up.fizz
index 0f1aa2d..5d58bf4 100644
--- a/migrations/20211126154047_create_messages.up.fizz
+++ b/migrations/20211126154047_create_messages.up.fizz
@@ -1,4 +1,5 @@
 create_table("messages") {
 	t.Column("id", "uuid", {primary: true})
+	t.Column("text", "string")
 	t.Timestamps()
 }
\ No newline at end of file
diff --git a/models/message.go b/models/message.go
index 5da404a..9012952 100644
--- a/models/message.go
+++ b/models/message.go
@@ -10,7 +10,8 @@ import (
 // Message is used by pop to map your messages database table to your go code.
 type Message struct {
     ID uuid.UUID `json:"id" db:"id"`
-    CreatedAt time.Time `json:"created_at" db:"created_at"`
+	Text string `json:"text" db:"text"`
+	CreatedAt time.Time `json:"created_at" db:"created_at"`
     UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
 }
 
@@ -32,7 +33,13 @@ func (m Messages) String() string {
 // Validate gets run every time you call a "pop.Validate*" (pop.ValidateAndSave, pop.ValidateAndCreate, pop.ValidateAndUpdate) method.
 // This method is not required and may be deleted.
 func (m *Message) Validate(tx *pop.Connection) (*validate.Errors, error) {
-	return validate.NewErrors(), nil
+	verrs := validate.NewErrors()
+
+	if len(m.Text) < 1 {
+		verrs.Add("Text", "Text must not be empty.")
+	}
+
+	return verrs, nil
 }
 
 // ValidateCreate gets run every time you call "pop.ValidateAndCreate" method.
diff --git a/templates/messages/_form.plush.html b/templates/messages/_form.plush.html
index bf0e0e3..c5b348c 100644
--- a/templates/messages/_form.plush.html
+++ b/templates/messages/_form.plush.html
@@ -1 +1,2 @@
+<%= f.InputTag("Text") %>
 <button class="btn btn-success" role="submit">Save</button>

Expected Behavior

A red text with the validation error message is shown below the input field.

Based on https://gobuffalo.io/en/docs/forms#error-handling I understand/assume that validation errors should be rendered when:

  • An instance of validation.Errors is added to the context using c.Set("errors", …)
  • The form is rendered using the formFor helper
  • The key used for validate.Errors.Add matches the key used for f.inputTag

Actual Behavior

No validation errror message is shown but there clearly was an validation error as no record was safed to the database.

Info

Please run buffalo info and paste the information below where it says "PASTE_HERE".

-> Go: Checking installation
✓ The `go` executable was found on your system at: /usr/local/bin/go

-> Go: Checking minimum version requirements
✓ Your version of Go, 1.17.3, meets the minimum requirements.

-> Go: Checking Package Management
✓ You are using Go Modules (`go`) for package management.

-> Go: Checking PATH
✓ Your PATH contains /Users/corvus/go/bin.

-> Node: Checking installation
✓ The `node` executable was found on your system at: /usr/local/bin/node

-> Node: Checking minimum version requirements
✓ Your version of Node, v16.10.0, meets the minimum requirements.

-> NPM: Checking installation
✓ The `npm` executable was found on your system at: /usr/local/bin/npm

-> NPM: Checking minimum version requirements
✓ Your version of NPM, 7.24.0, meets the minimum requirements.

-> Yarn: Checking installation
✓ The `yarnpkg` executable was found on your system at: /usr/local/bin/yarnpkg

-> Yarn: Checking minimum version requirements
✓ Your version of Yarn, 1.22.17, meets the minimum requirements.

-> PostgreSQL: Checking installation
✘ The `postgres` executable could not be found on your system.
For help setting up your Postgres environment please follow the instructions for you platform at:

https://www.postgresql.org/download/

-> MySQL: Checking installation
✘ The `mysql` executable could not be found on your system.
For help setting up your MySQL environment please follow the instructions for you platform at:

https://www.mysql.com/downloads/

-> SQLite3: Checking installation
✓ The `sqlite3` executable was found on your system at: /opt/local/bin/sqlite3

-> SQLite3: Checking minimum version requirements
✓ Your version of SQLite3, 3.36.0, meets the minimum requirements.

-> Cockroach: Checking installation
✘ The `cockroach` executable could not be found on your system.
For help setting up your Cockroach environment please follow the instructions for you platform at:

https://www.cockroachlabs.com/docs/stable/

-> Buffalo (CLI): Checking installation
✓ The `buffalo` executable was found on your system at: /usr/local/bin/buffalo

-> Buffalo (CLI): Checking minimum version requirements
✓ Your version of Buffalo (CLI), v0.18.0, meets the minimum requirements.

-> Buffalo: Application Details
Pwd         /Users/corvus/src/github.com/corvus-ch/app
Root        /Users/corvus/src/github.com/corvus-ch/app
GoPath      /Users/corvus/go
PackagePkg  app
ActionsPkg  app/actions
ModelsPkg   app/models
GriftsPkg   app/grifts
WithModules true
Name        app
Bin         bin/app
VCS         git
WithPop     true
WithSQLite  false
WithDep     false
WithWebpack true
WithNodeJs  true
WithYarn    true
WithDocker  true
WithGrifts  true
AsWeb       true
AsAPI       false
InApp       true
PackageJSON {map[build:webpack --mode production --progress dev:webpack --watch]}

-> Buffalo: config/buffalo-app.toml
name = "app"
bin = "bin/app"
vcs = "git"
with_pop = true
with_sqlite = false
with_dep = false
with_webpack = true
with_nodejs = true
with_yarn = true
with_docker = true
with_grifts = true
as_web = true
as_api = false

-> Buffalo: config/buffalo-plugins.toml
[[plugin]]
  binary = "buffalo-pop"
  go_get = "github.com/gobuffalo/buffalo-pop/v3@latest"

-> Buffalo: go.mod
module app

go 1.16

require (
	github.com/gobuffalo/buffalo v0.18.0
	github.com/gobuffalo/buffalo-pop/v3 v3.0.1
	github.com/gobuffalo/envy v1.10.1
	github.com/gobuffalo/mw-csrf v1.0.0
	github.com/gobuffalo/mw-forcessl v0.0.0-20200131175327-94b2bd771862
	github.com/gobuffalo/mw-i18n/v2 v2.0.1
	github.com/gobuffalo/mw-paramlogger v1.0.0
	github.com/gobuffalo/pop/v6 v6.0.0
	github.com/gobuffalo/suite/v4 v4.0.2
	github.com/gobuffalo/validate/v3 v3.3.1
	github.com/gobuffalo/x v0.0.0-20190224155809-6bb134105960
	github.com/gofrs/uuid v4.1.0+incompatible
	github.com/markbates/grift v1.5.0
	github.com/unrolled/secure v1.0.9
)
sio4 commented

If the real situation of your validation is not complex, I would like to say you'd better use provided validators. So your code could be changed as:

	return validate.Validate(
		&validators.StringIsPresent{
			Name:    "Text",
			Field:   m.Text,
			Message: "empty value is not allowed",
		},
	), nil

(Message is optional) instead of

	verrs := validate.NewErrors()
	if len(m.Text) < 1 {
		verrs.Add("Text", "Text must not be empty.")
	}
	return verrs, nil

However, if you really need to write your own validator with detailed logic and just want to add the result to the verrs, you can fix your code as follow:

verrs.Add("text", "Text must not be empty")

("text" part) or

verrs.Add(validators.GenerateKey("Text"), "Text must not be empty")

I hope this answer could help you to enjoy riding Buffalo!

@sio4 thanks for your reply. I could have sworn I also tried lowercaseing the field name. But yes, using a lowercase version of the field name and ord using validatores.GenerateKey() resolves my issue.

As for standard validations, I do agree with using existing ones. The example at hand was used to have something simple to learn the concept.

sio4 commented

Nice to see your confirmation of using lowercase and validators.GenerateKey() helped you!
I agree that using a simpler API such as verrs.Add() could be good.
Have a nice weekend!