Skip to content

Commit

Permalink
feat(form): add Collection type
Browse files Browse the repository at this point in the history
  • Loading branch information
rande committed Sep 6, 2023
1 parent 7a4de0e commit a2c6009
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 16 deletions.
100 changes: 84 additions & 16 deletions core/form/form_structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ var (

var replacers = strings.NewReplacer(".", "_", "[", "_", "]", "")

type FieldCollectionValue struct {
Value interface{}
Key string
}

type FieldCollectionOptions struct {
Items []*FieldCollectionValue
Configure func(value interface{}) *Form
}

type FieldOption struct {
Label string
Checked bool
Expand Down Expand Up @@ -104,6 +114,14 @@ func (f *FormField) Value(name string) interface{} {
return nil
}

func (f *FormField) Add(name string, fieldType string, value interface{}) *FormField {
field := create(name, fieldType, value)

f.Children = append(f.Children, field)

return field
}

type Form struct {
Fields []*FormField
State string
Expand All @@ -113,6 +131,9 @@ type Form struct {
func defaultMarshal(field *FormField, form *Form) error {
field.Input.Value = fmt.Sprintf("%s", field.InitialValue)

field.Input.Name = fmt.Sprintf("%s%s", field.Prefix, field.Name)
field.Input.Id = replacers.Replace(field.Input.Name)

return nil
}

Expand All @@ -134,7 +155,7 @@ func defaultUnmarshal(field *FormField, form *Form, values url.Values) error {
}

func formMarshal(field *FormField, form *Form) error {
subForm := form.Get(field.Name).InitialValue.(*Form)
subForm := field.InitialValue.(*Form)

field.Children = subForm.Fields

Expand All @@ -159,6 +180,42 @@ func formUnmarshal(field *FormField, form *Form, values url.Values) error {
return nil
}

func collectionMarshal(field *FormField, form *Form) error {
options := field.InitialValue.(*FieldCollectionOptions)

field.Input.Name = fmt.Sprintf("%s%s", field.Prefix, field.Name)
field.Input.Id = replacers.Replace(field.Input.Name)

for _, value := range options.Items {
subForm := options.Configure(value.Value)

subField := create(value.Key, "form", subForm)
subField.Input.Name = fmt.Sprintf("%s[%s]", field.Input.Name, value.Key)
subField.Input.Id = replacers.Replace(subField.Input.Name)
subField.Prefix = field.Input.Name + "."

fmt.Printf("collectionMarshal: %s\n", subField.Input.Name)

field.Children = append(field.Children, subField)

subField.Marshal(subField, form)
}

return nil
}

func collectionUnmarshal(field *FormField, form *Form, values url.Values) error {
options := field.InitialValue.(*FieldCollectionOptions)

for _, value := range options.Items {
subField := field.Get(value.Key)

subField.Unmarshal(subField, form, values)
}

return nil
}

func checkboxMarshal(field *FormField, form *Form) error {

field.Input.Name = fmt.Sprintf("%s%s", field.Prefix, field.Name)
Expand Down Expand Up @@ -243,6 +300,31 @@ func (f *Form) Value(name string) interface{} {
return nil
}

func create(name string, fieldType string, value interface{}) *FormField {
field := CreateFormField()
field.Name = name
field.Input.Type = fieldType
field.Label.Value = name
field.InitialValue = value

if fieldType == "checkbox" {
field.Marshal = checkboxMarshal
field.Unmarshal = checkboxUnmarshal
}

if fieldType == "form" {
field.Marshal = formMarshal
field.Unmarshal = formUnmarshal
}

if fieldType == "collection" {
field.Marshal = collectionMarshal
field.Unmarshal = collectionUnmarshal
}

return field
}

func CreateForm() *Form {
return &Form{}
}
Expand Down Expand Up @@ -280,21 +362,7 @@ func CreateFormField() *FormField {
}

func (f *Form) Add(name string, fieldType string, value interface{}) *Form {
field := CreateFormField()
field.Name = name
field.Input.Type = fieldType
field.Label.Value = name
field.InitialValue = value

if fieldType == "checkbox" {
field.Marshal = checkboxMarshal
field.Unmarshal = checkboxUnmarshal
}

if fieldType == "form" {
field.Marshal = formMarshal
field.Unmarshal = formUnmarshal
}
field := create(name, fieldType, value)

f.Fields = append(f.Fields, field)

Expand Down
45 changes: 45 additions & 0 deletions core/form/form_structs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,48 @@ func Test_Bind_Form_Nested_Basic(t *testing.T) {

assert.True(t, form.Get("post").Get("options").SubmitedValue.(FieldOptions)["admin"].Checked)
}

type Tag struct {
Id int
Name string
Enabled bool
}

func Test_Bind_Form_Collection(t *testing.T) {
values := []*FieldCollectionValue{
{Key: "0", Value: &Tag{Id: 1, Name: "tag1", Enabled: true}},
{Key: "1", Value: &Tag{Id: 1, Name: "tag2", Enabled: true}},
}

form := &Form{}
form.Add("tags", "collection", &FieldCollectionOptions{
Items: values,
Configure: func(value interface{}) *Form {
tag := value.(*Tag)

tagForm := &Form{}
tagForm.Add("name", "text", tag.Name)
tagForm.Add("options", "checkbox", FieldOptions{
"enabled": {Label: "Is Enabled", Checked: tag.Enabled},
})

return tagForm
},
})

PrepareForm(form)

assert.Equal(t, form.Get("tags").Get("0").Get("name").Input.Name, "tags[0].name")

v := url.Values{
"tags[0].name": []string{"TAG 1"},
"tags[0].options[enabled]": []string{"false"},
"tags[1].name": []string{"TAG 2"},
"tags[1].options[enabled]": []string{"false"},
}

BindUrlValues(form, v)

assert.NotNil(t, form.Get("tags").Get("0").Get("name").SubmitedValue, "TAG 1")

}

0 comments on commit a2c6009

Please sign in to comment.