Open ghost opened 9 years ago
Looking forward to the autoform !
OK, first the validation part of autoforms. I lean toward the following option:
models
package in user's app.struct
tags and methods is used:package models
type User struct {
Name string `autoform:"Required(true) LenRange(2,64)"`
Age int `autoform:"Min(12) Max(120)"`
}
// `field` is a name of struct's field (e.g. "Name" or "Age").
// `value` is what we receive from user (it's automatically converted from `string`).
//
// the rest of parameters are extracted from struct tags.
func (m *User) Required(field, value string, required bool) error {
if value == "" {
return fmt.Errorf("%v must not be empty", field)
}
return nil
}
func (m *User) Min(field string, value int, min int) error {
if value > min {
return fmt.Errorf("%v must be less than %d", field, min, max)
}
return nil
}
func (m *User) LenRange(field, value string, min, max int) error {...}
func (m *User) Max(field string, value int, max int) error {...}
type User struct {
*text.Validators
*integers.Validators
Name string `autoform:"Required(true) LenRange(2,64)"`
Age int `autoform:"Min(12) Max(120)"`
}
So the validators won't be built in but rather the mechanism will be extendible and customizable.
Now a few things:
`Required(true) LenRange(2,64)`
field, value string
part of validators' input arguments looks ugly. Too much boilerplate code.@xpbliss Thank you for your input, I'll check those packages out.
Why not release new updates for the goal?
How about the auto form
?
Since this a code gen tool, would it be a good idea to generate the struct from a database schema ?
With regards to the validation case for password, confirm password, you probably need a method to validate a form in it's entirety after all fields have been validated. It may not always make sense to add a validation to a specific field. This method will probably need access to the form post parameters as well.
With regards to the validation case for password, confirm password, you probably need a method to validate a form in it's entirety after all fields have been validated.
@hqdo, yeah you're right. I'll keep this use-case in mind.
Since this a code gen tool, would it be a good idea to generate the struct from a database schema?
Yes, it is a good idea. For now the priority is to implement autoform
to support:
// SomeAction is a sample action. Its form's fields will be automatically binded
// to the values in r.Request.Form.
func (c *Controller) SomeAction(form MyForm) http.Handler {
}
if errs := form.Errors() {
...
}
c.Context["myForm"] = form
return c.Render()
As soon as this is ready we can focus on generation of struct
s from DB schema.
Why not make goal generate everything statically from a defined schema (could be the Struct in your examples) or from database ? binding, validation, forms (template) all statically generated.
This means no magic, no reflection (during runtime) and much easier for the user to customize in a real application. I've found auto generators (eg. django) impressive for quick demos, but are a pain to customise when you start needing to make changes to the runtime generated stuff.
@hqdo Well, that's how we are going to do it. Everything is generated from struct
s. And then can be used from actions. No runtime reflection is intended.
looking forward to it ! the soon the better!
@alkchr sorry i may have misunderstood. seeing the following code from your example, i thought the form rendering would be a black box method. Sounds good if everything is generated and we can freely edit the default output.
c.Context["myForm"] = form
return c.Render()
Creation and validation of forms is IMO the most boring part of web-development. Let's make it fun again. The use-case is:
We could possibly use struct tags for that. E.g.:
Though this is not type safe. Alternatively, we can apply a "magic methods" approach we use for the controllers.
Related functionality in other frameworks