add constraints
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
Simon Vieille 2025-07-22 21:34:33 +02:00
commit 35c01fa7ca
Signed by: deblan
GPG key ID: 579388D585F70417
13 changed files with 415 additions and 137 deletions

View file

@ -1,6 +1,126 @@
---
linkTitle: Constraints
title: Constraints
weight: 4
weight: 5
---
The validation is designed to validate data against constraints.
## Import
```golang
import (
"gitnet.fr/deblan/go-form/validation"
)
```
## Constraints
### Length
Validate the length of an array, a slice or a string
```golang
c := validation.NewLength()
// Define minimum
c.WithMin(1)
// Define minimum
c.WithMax(100)
// Define min and max
// Equivalent to c.WithMin(50).WithMax(50)
c.WithExact(50)
```
### Mail
```golang
validation.NewMail()
```
### Not blank
```golang
validation.NewNotBlank()
```
### Range
Validate a number
```golang
c := validation.NewRange()
// Define minimum
c.WithMin(1)
// Define minimum
c.WithMax(100)
// Define min and max
// Equivalent to c.WithMin(1).WithMax(100)
c.WithRange(1, 100)
```
### Regex
Validate a string with a regex
```golang
c := validation.NewRegex(`expression`)
// The value must match
c.MustMatch()
// The value must not match
c.MustNotMatch()
```
## Custom constraint
Use case: you want to validate that the data is an even number.
```golang
package validation
import (
"strconv"
v "gitnet.fr/deblan/go-form/validation"
)
// Define a struct
type IsEven struct {
Message string
TypeErrorMessage string
}
// Create a factory
func NewIsEven() IsEven {
return IsEven{
Message: "This value is not an even number.",
TypeErrorMessage: "This value can not be processed.",
}
}
// Implement the validation
func (c IsEven) Validate(data any) []Error {
errors := []Error{}
// The constraint should not validate an empty data
if len(v.NewNotBlank().Validate(data)) == 0 {
i, err := strconv.Atoi(data.(string))
if err != nil {
errors = append(errors, Error(c.TypeErrorMessage))
} else if i%2 != 0 {
errors = append(errors, Error(c.Message))
}
}
return errors
}
```

View file

@ -4,40 +4,299 @@ title: Fields
weight: 4
---
The documentation of field is realised with this program.
A field represents a field in a form.
```golang {hl_lines=[12,13]}
import (
"bytes"
"fmt"
"html/template"
## Struct
"gitnet.fr/deblan/go-form/form"
"gitnet.fr/deblan/go-form/theme"
)
func main() {
myForm := form.NewForm(
// the documented field here
// form.NewField...
).
WithName("form").
End()
render := theme.NewRenderer(theme.Html5)
tpl, _ := template.New("example").Funcs(render.FuncMap()).Parse(`{{- form .Form -}}`)
var buffer bytes.Buffer
tpl.Execute(&buffer, map[string]any{
"Form": myForm,
})
fmt.Print(buffer.String())
```golang
type Field struct {
Name string
Widget string
Data any
Options []*Option
Children []*Field
Constraints []validation.Constraint
Errors []validation.Error
PrepareView func() map[string]any
BeforeMount func(data any) (any, error)
BeforeBind func(data any) (any, error)
Validate func(f *Field) bool
IsSlice bool
IsFixedName bool
Form *Form
Parent *Field
}
```
## Common options
## Fields
```golang
func NewField(name, widget string) *Field
```
Generates a new field with default properties It should not be used directly but inside function like in form.NewFieldText
### Checkbox
```golang
func NewFieldCheckbox(name string) *Field
```
Generates an input[type=checkbox]
### Choice
```golang
func NewFieldChoice(name string) *Field
```
Generates inputs (checkbox or radio) or selects
### Csrf
```golang
func NewFieldCsrf(name string) *Field
```
### Date
```golang
func NewFieldDate(name string) *Field
```
Generates an input[type=date] with default transformers
### Datetime
```golang
func NewFieldDatetime(name string) *Field
```
Generates an input[type=datetime] with default transformers
### DatetimeLocal
```golang
func NewFieldDatetimeLocal(name string) *Field
```
Generates an input[type=datetime-local] with default transformers
### Hidden
```golang
func NewFieldHidden(name string) *Field
```
Generates an input[type=hidden]
### Mail
```golang
func NewFieldMail(name string) *Field
```
Generates an input[type=email]
### Number
```golang
func NewFieldNumber(name string) *Field
```
Generates an input[type=number] with default transformers
### Password
```golang
func NewFieldPassword(name string) *Field
```
Generates an input[type=password]
### Range
```golang
func NewFieldRange(name string) *Field
```
Generates an input[type=range]
### Sub Form
```golang
func NewFieldSubForm(name string) *Field
```
Alias:
```golang
func NewSubForm(name string) *Field
```
Generates a sub form
### Text
```golang
func NewFieldText(name string) *Field
```
Generates an input[type=text]
### Textarea
```golang
func NewFieldTextarea(name string) *Field
```
Generates a textarea
### Time
```golang
func NewFieldTime(name string) *Field
```
Generates an input[type=time] with default transformers
### Submit
```golang
func NewSubmit(name string) *Field
```
Generates an input[type=submit]
## Methods
### Add
```golang
func (f *Field) Add(children ...*Field) *Field
```
Appends children
### Bind
```golang
func (f *Field) Bind(data map[string]any, key *string) error
```
Bind the data into the given map
### GetChild
```golang
func (f *Field) GetChild(name string) *Field
```
Returns a child using its name
### GetId
```golang
func (f *Field) GetId() string
```
Computes the id of the field
### GetName
```golang
func (f *Field) GetName() string
```
Computes the name of the field
### GetOption
```golang
func (f *Field) GetOption(name string) *Option
```
Returns an option using its name
### HasChild
```golang
func (f *Field) HasChild(name string) bool
```
Checks if the field contains a child using its name
### HasOption
```golang
func (f *Field) HasOption(name string) bool
```
Checks if the field contains an option using its name
### Mount
```golang
func (f *Field) Mount(data any) error
```
Populates the field with data
### ResetErrors
```golang
func (f *Field) ResetErrors() *Field
```
Resets the field errors
### WithBeforeBind
```golang
func (f *Field) WithBeforeBind(callback func(data any) (any, error)) *Field
```
Sets a transformer applied to the data of a field before defining it in a structure
### WithBeforeMount
```golang
func (f *Field) WithBeforeMount(callback func(data any) (any, error)) *Field
```
Sets a transformer applied to the structure data before displaying it in a field
### WithConstraints
```golang
func (f *Field) WithConstraints(constraints ...validation.Constraint) *Field
```
Appends constraints
### WithData
```golang
func (f *Field) WithData(data any) *Field
```
Sets data the field
### WithFixedName
```golang
func (f *Field) WithFixedName() *Field
```
Sets that the name of the field is not computed
### WithOptions
```golang
func (f *Field) WithOptions(options ...*Option) *Field
```
#### Common options
| Name | type | description | Info |
| ---- | ---- | ---- | ---- |
@ -47,3 +306,13 @@ func main() {
| `label` | `string` | The label of the field | Usually show before the field |
| `label_attr` | `map[string]string` | List of extra attributes of the label | |
| `help` | `string` | Helper of the field | |
Appends options to the field
### WithSlice
```golang
func (f *Field) WithSlice() *Field
```
Sets that the field represents a data slice

View file

@ -1,5 +0,0 @@
---
linkTitle: Date
title: Date
---

View file

@ -1,5 +0,0 @@
---
linkTitle: Datetime
title: Datetime
---

View file

@ -1,6 +0,0 @@
---
linkTitle: Hidden
title: Hidden
weight: 2
---

View file

@ -1,10 +0,0 @@
---
linkTitle: Mail
title: Mail
---
<table>
<tr>
<td>ok</td>
</tr>
</table>

View file

@ -1,10 +0,0 @@
---
linkTitle: Number
title: Number
---
<table>
<tr>
<td>ok</td>
</tr>
</table>

View file

@ -1,10 +0,0 @@
---
linkTitle: Password
title: Password
---
<table>
<tr>
<td>ok</td>
</tr>
</table>

View file

@ -1,10 +0,0 @@
---
linkTitle: Range
title: Range
---
<table>
<tr>
<td>ok</td>
</tr>
</table>

View file

@ -1,50 +0,0 @@
---
linkTitle: Text
title: Text
weight: 1
---
## Basic example
{{< tabs items="GO,Result" >}}
{{< tab >}}
```golang
form.NewFieldText("Name")
```
{{< /tab >}}
{{< tab >}}
```html
<form action="" method="POST" >
<div >
<input id="form-name" name="form[Name]" value="" type="text" >
</div>
</form>
```
{{< /tab >}}
{{< /tabs >}}
## Fully featured example
{{< tabs items="GO,Result" >}}
{{< tab >}}
```golang
form.NewFieldText("Name").
WithOptions(
form.NewOption("label", "Name"),
form.NewOption("required", true),
form.NewOption("attr", map[string]string{"data-foo": "foo"}),
form.NewOption("row_attr", map[string]string{"data-bar": "bar"}),
)
```
{{< /tab >}}
{{< tab >}}
```html
<form action="" method="POST" >
<div data-bar="bar">
<label for="form-name" >Name</label>
<input id="form-name" required="required" name="form[Name]" value="" type="text" data-foo="foo">
</div>
</form>
```
{{< /tab >}}
{{< /tabs >}}

View file

@ -1,5 +0,0 @@
---
linkTitle: Time
title: Time
---