From 35c01fa7cab99e49feaf02b72ab64eb2bb1f70e7 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Tue, 22 Jul 2025 21:34:33 +0200 Subject: [PATCH] add constraints --- content/docs/constraints/_index.md | 122 +++++++++- content/docs/fields/_index.md | 327 +++++++++++++++++++++++--- content/docs/fields/button.md | 0 content/docs/fields/input/date.md | 5 - content/docs/fields/input/datetime.md | 5 - content/docs/fields/input/hidden.md | 6 - content/docs/fields/input/mail.md | 10 - content/docs/fields/input/number.md | 10 - content/docs/fields/input/password.md | 10 - content/docs/fields/input/range.md | 10 - content/docs/fields/input/text.md | 50 ---- content/docs/fields/input/time.md | 5 - content/docs/fields/textarea.md | 0 13 files changed, 419 insertions(+), 141 deletions(-) delete mode 100644 content/docs/fields/button.md delete mode 100644 content/docs/fields/input/date.md delete mode 100644 content/docs/fields/input/datetime.md delete mode 100644 content/docs/fields/input/hidden.md delete mode 100644 content/docs/fields/input/mail.md delete mode 100644 content/docs/fields/input/number.md delete mode 100644 content/docs/fields/input/password.md delete mode 100644 content/docs/fields/input/range.md delete mode 100644 content/docs/fields/input/text.md delete mode 100644 content/docs/fields/input/time.md delete mode 100644 content/docs/fields/textarea.md diff --git a/content/docs/constraints/_index.md b/content/docs/constraints/_index.md index 3d5e904..8783a98 100644 --- a/content/docs/constraints/_index.md +++ b/content/docs/constraints/_index.md @@ -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 +} +``` + diff --git a/content/docs/fields/_index.md b/content/docs/fields/_index.md index c2641b7..a32a920 100644 --- a/content/docs/fields/_index.md +++ b/content/docs/fields/_index.md @@ -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 diff --git a/content/docs/fields/button.md b/content/docs/fields/button.md deleted file mode 100644 index e69de29..0000000 diff --git a/content/docs/fields/input/date.md b/content/docs/fields/input/date.md deleted file mode 100644 index 6555c18..0000000 --- a/content/docs/fields/input/date.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -linkTitle: Date -title: Date ---- - diff --git a/content/docs/fields/input/datetime.md b/content/docs/fields/input/datetime.md deleted file mode 100644 index bc33e0a..0000000 --- a/content/docs/fields/input/datetime.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -linkTitle: Datetime -title: Datetime ---- - diff --git a/content/docs/fields/input/hidden.md b/content/docs/fields/input/hidden.md deleted file mode 100644 index 9293d96..0000000 --- a/content/docs/fields/input/hidden.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -linkTitle: Hidden -title: Hidden -weight: 2 ---- - diff --git a/content/docs/fields/input/mail.md b/content/docs/fields/input/mail.md deleted file mode 100644 index 7a7f44b..0000000 --- a/content/docs/fields/input/mail.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -linkTitle: Mail -title: Mail ---- - - - - - -
ok
diff --git a/content/docs/fields/input/number.md b/content/docs/fields/input/number.md deleted file mode 100644 index 89ae187..0000000 --- a/content/docs/fields/input/number.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -linkTitle: Number -title: Number ---- - - - - - -
ok
diff --git a/content/docs/fields/input/password.md b/content/docs/fields/input/password.md deleted file mode 100644 index 37c761f..0000000 --- a/content/docs/fields/input/password.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -linkTitle: Password -title: Password ---- - - - - - -
ok
diff --git a/content/docs/fields/input/range.md b/content/docs/fields/input/range.md deleted file mode 100644 index a085305..0000000 --- a/content/docs/fields/input/range.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -linkTitle: Range -title: Range ---- - - - - - -
ok
diff --git a/content/docs/fields/input/text.md b/content/docs/fields/input/text.md deleted file mode 100644 index 5badb2b..0000000 --- a/content/docs/fields/input/text.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -linkTitle: Text -title: Text -weight: 1 ---- - -## Basic example - -{{< tabs items="GO,Result" >}} - {{< tab >}} -```golang -form.NewFieldText("Name") -``` - {{< /tab >}} - {{< tab >}} -```html -
-
- -
-
-``` - {{< /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 -
-
- - -
-
-``` - {{< /tab >}} -{{< /tabs >}} diff --git a/content/docs/fields/input/time.md b/content/docs/fields/input/time.md deleted file mode 100644 index e084646..0000000 --- a/content/docs/fields/input/time.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -linkTitle: Time -title: Time ---- - diff --git a/content/docs/fields/textarea.md b/content/docs/fields/textarea.md deleted file mode 100644 index e69de29..0000000