I found no sufficient forms library in GO, so I decided to write one by my self. ;-)
The main goal is separate validation from field rendering, so you won't find here silly structures like:
Field{Required: True}
Validate if user entered any data should be done in validation, and if you want <input />
to have a required
attribute, you need to set this in field's attributes.
Here is a basic usage for forms. Keep in mind, that validation is separated from field, and inputs and albels HTML attributes are also separated.
import (
"fmt"
"net/http"
"github.com/Alkemic/forms"
)
func someView(w http.ResponseWriter, r *http.Request) {
form := forms.New(
map[string]*forms.Field{
"email": &forms.Field{
Validators: []forms.Validator{
&forms.Required{},
},
},
"password": &forms.Field{
Type: &forms.InputPassword{},
Validators: []forms.Validator{
&forms.Required{},
},
},
},
forms.Attributes{"id": "login-form"},
)
if form.IsValid(r.PostForm) {
// if valid you can access cleaned data in attribute CleanedData
for k, v := range form.CleanedData{
fmt.Println("key:", k, "value:", v)
}
} else {
// else not ;-)
}
}
I've decided to don't write whole form rendering method, because, let's be honest, it won't give level of control over form that we need and in the end you will have to do it by yourself. Insted of there are methods that will help you with displaying form.
{{.Form.OpenTag}}
{{if .Form.Fields.email.HasErrors}}
{{.Form.Fields.email.RenderErrors}}
{{end}}
{{.Form.Fields.email.RenderLabel}}
{{.Form.Fields.email.Render}}
{{if .Form.Fields.password.HasErrors}}
{{.Form.Fields.password.RenderErrors}}
{{end}}
{{.Form.Fields.password.RenderLabel}}
{{.Form.Fields.password.Render}}
{{.Form.CloseTag}}
Eventually you can render errors by yourself
{{if .Form.Fields.email.HasErrors}}
<ul>
{{range .Form.Fields.email.Errors}}
<li class="error">{{.}}</li>
{{end}}
</ul>
{{end}}
As usual, no magic here:
$ go get github.com/Alkemic/forms
Fields are representation of single field in form, it's a container for validators and attributes.
Field{
Type: &Input{},
Validators: []Validator{
&Required{},
},
Attributes{"id": "test"},
Label: "Test label",
LabelAttributes: Attributes{
"required": "required",
"id": "test",
"attr": "value",
},
}
When fields label is rendered (field.RenderLabel
) attribute for
is automaticly added as well
as attribute id
to field.
Types are responsible for field behavior: rendering, cleaning data and giving information if field accept multiple value. Generally you should not access fields type directly, as its used by field.
The incoming data need to be cleaned after succesful validation, and before we give them to user.
By clean, we mean that we convert them to format/
All of this transformation are done by method CleanData
on Type
.
For example, when we crate Field
with type NumberInput
in form.CleanedData
we
find a number (int
), for MultiSelect
we find a slice with all selected values.
Big fat note: this library is under development, and it's API may or may not change. Currently this library works, but I don't recomend this for prodution or even thinking about production usage. ;-)
- Field rendering
- Initial data support
- Internationalization
- Field types (inc. types introduced in HTML5)
- Input
- Textarea
- Radio
- Select
- Number
- Color
- File
- Hidden
- Image
- Month
- Password
- Range
- Telephone
- Time
- URL
- Week
- Date
- Datetime
- Datetime-local
- Validators
- Regexp
- Required
- MinLength
- MaxLength
- InSlice
- MinValue
- MaxValue
- URL
- Date
- Time
- DateTime