Skip to content

Commit

Permalink
feat(form): add slice management
Browse files Browse the repository at this point in the history
  • Loading branch information
rande committed Oct 26, 2023
1 parent 20bd17a commit 989fe5e
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 5 deletions.
2 changes: 1 addition & 1 deletion core/form/form_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func ValueToStr(value interface{}, src reflect.Value) (string, bool) {
return "", false
}

fmt.Printf("ValueToStr: %s - %s, %s\n", value, src.Kind(), src.Kind())
//fmt.Printf("ValueToStr: %s - %s, %s\n", value, src.Kind(), src.Kind())

switch src.Kind() {

Expand Down
36 changes: 34 additions & 2 deletions core/form/form_marshaller.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ type MarshallerResult struct {
}

func findMarshaller(rv reflect.Value) *MarshallerResult {

if rv.Kind() == reflect.String {
return &MarshallerResult{
Marshaller: defaultMarshal,
Expand Down Expand Up @@ -155,7 +154,6 @@ func findMarshaller(rv reflect.Value) *MarshallerResult {
}

func configure(field *FormField, form *Form) {

if form.Data != nil && field.InitialValue == nil {
field.reflect = form.reflect.FieldByName(field.Name)
}
Expand Down Expand Up @@ -186,10 +184,44 @@ func configure(field *FormField, form *Form) {
func sliceMarshal(field *FormField, form *Form) error {
defaultMarshal(field, form)

values := []string{}

for i := 0; i < field.reflect.Len(); i++ {
v := field.reflect.Index(i)
values = append(values, v.String())
}

field.Input.Value = strings.Join(values, ", ")

return nil
}

func sliceUnmarshal(field *FormField, form *Form, values url.Values) error {
defaultUnmarshal(field, form, values)

parts := strings.Split(field.SubmittedValue.(string), ",")

for i, part := range parts {
parts[i] = strings.TrimSpace(part)
}

// transform the final slice to the correct type
slice := reflect.MakeSlice(reflect.SliceOf(field.reflect.Type().Elem()), 0, 0)
value := reflect.Zero(field.reflect.Type().Elem())

for _, part := range parts {
if v, ok := StrToValue(part, value); ok {
rv := reflect.ValueOf(v)
if len(rv.String()) == 0 {
continue
}

slice = reflect.Append(slice, reflect.ValueOf(v))
}
}

field.SubmittedValue = slice.Interface()
field.Touched = true

return nil
}
Expand Down
34 changes: 34 additions & 0 deletions core/form/form_marshaller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"testing"
"time"

"github.com/rande/gonode/modules/base"
"github.com/rande/gonode/modules/blog"
"github.com/stretchr/testify/assert"
)

Expand Down Expand Up @@ -43,3 +45,35 @@ func Test_Date_Unmarshalling(t *testing.T) {

assert.Equal(t, expectedDate, field.SubmittedValue)
}

func Test_Date_Unmarshalling_With_Time(t *testing.T) {
node := base.NewNode()
handler := &blog.PostHandler{}
node.Data, node.Meta = handler.GetStruct()

form := CreateForm(node)
form.Add("UpdatedAt", "date")

dataForm := CreateForm(node.Data)
dataForm.Add("PublicationDate", "date")

form.Add("data", "form", dataForm)

PrepareForm(form)

v := url.Values{
"UpdatedAt": []string{"2022-04-01"},
"data.PublicationDate": []string{
"2022-04-01",
},
}

BindUrlValues(form, v)

ValidateForm(form)

AttachValues(form)

assert.Equal(t, time.Date(2022, time.April, 1, 0, 0, 0, 0, time.UTC), node.UpdatedAt)
assert.Equal(t, time.Date(2022, time.April, 1, 0, 0, 0, 0, time.UTC), node.Data.(*blog.Post).PublicationDate)
}
27 changes: 27 additions & 0 deletions core/form/form_structs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type TestUser struct {
Ratio float32
DOB time.Time
Items []int32
Tags []string
}

type TestBlogPost struct {
Expand Down Expand Up @@ -582,3 +583,29 @@ func Test_Bind_Form_Select_Invalid_Type(t *testing.T) {

assert.NotNil(t, err)
}

func Test_Form_Tags_As_String(t *testing.T) {
user := &TestUser{
Tags: []string{"foo", "bar"},
}

form := CreateForm(user)
form.Add("Tags")

PrepareForm(form)

assert.Equal(t, "foo, bar", form.Get("Tags").Input.Value)

v := url.Values{
"Tags": []string{"boo, far"},
}

BindUrlValues(form, v)

ValidateForm(form)

AttachValues(form)

assert.False(t, form.HasErrors)
assert.Equal(t, []string{"boo", "far"}, user.Tags)
}
14 changes: 12 additions & 2 deletions core/form/form_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"net/http"
"net/url"
"reflect"
"time"
)

const (
Expand Down Expand Up @@ -167,9 +168,18 @@ func attachValues(fields []*FormField) {
}

newValue := reflect.ValueOf(field.SubmittedValue)
// fmt.Printf("attachValues > Field name: %s, value: %s\n", field.Name, newValue)
// fmt.Printf("attachValues > Field name: %s, type: %s, value: %s\n", field.Name, field.reflect.Type(), newValue)
if newValue.CanConvert(field.reflect.Type()) {
field.reflect.Set(newValue.Convert(field.reflect.Type()))
// v := newValue.Convert(field.reflect.Type())
// fmt.Printf("attachValues > Field name: %s, type: %s, value: %s\n", field.Name, field.reflect.Type(), v)
// fmt.Printf("attachValues > %s\n", field.reflect)

if field.reflect.Type() == reflect.TypeOf(time.Time{}) {
field.reflect.Set(newValue)
} else {
field.reflect.Set(newValue.Convert(field.reflect.Type()))
}

} else {
// fmt.Printf("attachValues > Unable to convert type: Type, field: %s (kind: %s) submitted: %s, value: %s\n", field.Name, field.reflect.Kind(), newValue.Kind(), newValue.Interface())
}
Expand Down

0 comments on commit 989fe5e

Please sign in to comment.