diff --git a/templatefunc.go b/templatefunc.go index 36442984..01751717 100644 --- a/templatefunc.go +++ b/templatefunc.go @@ -280,15 +280,8 @@ func AssetsCSS(src string) template.HTML { } // ParseForm will parse form values to struct via tag. -func ParseForm(form url.Values, obj interface{}) error { - objT := reflect.TypeOf(obj) - objV := reflect.ValueOf(obj) - if !isStructPtr(objT) { - return fmt.Errorf("%v must be a struct pointer", obj) - } - objT = objT.Elem() - objV = objV.Elem() - +// Support for anonymous struct. +func parseFormToStruct(form url.Values, objT reflect.Type, objV reflect.Value) error { for i := 0; i < objT.NumField(); i++ { fieldV := objV.Field(i) if !fieldV.CanSet() { @@ -296,6 +289,14 @@ func ParseForm(form url.Values, obj interface{}) error { } fieldT := objT.Field(i) + if fieldT.Anonymous && fieldT.Type.Kind() == reflect.Struct { + err := parseFormToStruct(form, fieldT.Type, fieldV) + if err != nil { + return err + } + continue + } + tags := strings.Split(fieldT.Tag.Get("form"), ",") var tag string if len(tags) == 0 || len(tags[0]) == 0 { @@ -384,6 +385,19 @@ func ParseForm(form url.Values, obj interface{}) error { return nil } +// ParseForm will parse form values to struct via tag. +func ParseForm(form url.Values, obj interface{}) error { + objT := reflect.TypeOf(obj) + objV := reflect.ValueOf(obj) + if !isStructPtr(objT) { + return fmt.Errorf("%v must be a struct pointer", obj) + } + objT = objT.Elem() + objV = objV.Elem() + + return parseFormToStruct(form, objT, objV) +} + var sliceOfInts = reflect.TypeOf([]int(nil)) var sliceOfStrings = reflect.TypeOf([]string(nil)) diff --git a/templatefunc_test.go b/templatefunc_test.go index 86de37ae..a1ec1136 100644 --- a/templatefunc_test.go +++ b/templatefunc_test.go @@ -110,6 +110,17 @@ func TestHtmlunquote(t *testing.T) { } func TestParseForm(t *testing.T) { + type ExtendInfo struct { + Hobby string `form:"hobby"` + Memo string + } + + type OtherInfo struct { + Organization string `form:"organization"` + Title string `form:"title"` + ExtendInfo + } + type user struct { ID int `form:"-"` tag string `form:"tag"` @@ -119,19 +130,24 @@ func TestParseForm(t *testing.T) { Intro string `form:",textarea"` StrBool bool `form:"strbool"` Date time.Time `form:"date,2006-01-02"` + OtherInfo } u := user{} form := url.Values{ - "ID": []string{"1"}, - "-": []string{"1"}, - "tag": []string{"no"}, - "username": []string{"test"}, - "age": []string{"40"}, - "Email": []string{"test@gmail.com"}, - "Intro": []string{"I am an engineer!"}, - "strbool": []string{"yes"}, - "date": []string{"2014-11-12"}, + "ID": []string{"1"}, + "-": []string{"1"}, + "tag": []string{"no"}, + "username": []string{"test"}, + "age": []string{"40"}, + "Email": []string{"test@gmail.com"}, + "Intro": []string{"I am an engineer!"}, + "strbool": []string{"yes"}, + "date": []string{"2014-11-12"}, + "organization": []string{"beego"}, + "title": []string{"CXO"}, + "hobby": []string{"Basketball"}, + "memo": []string{"nothing"}, } if err := ParseForm(form, u); err == nil { t.Fatal("nothing will be changed") @@ -164,6 +180,18 @@ func TestParseForm(t *testing.T) { if y != 2014 || m.String() != "November" || d != 12 { t.Errorf("Date should equal `2014-11-12`, but got `%v`", u.Date.String()) } + if u.Organization != "beego" { + t.Errorf("Organization should equal `beego`, but got `%v`", u.Organization) + } + if u.Title != "CXO" { + t.Errorf("Title should equal `CXO`, but got `%v`", u.Title) + } + if u.Hobby != "Basketball" { + t.Errorf("Hobby should equal `Basketball`, but got `%v`", u.Hobby) + } + if len(u.Memo) != 0 { + t.Errorf("Memo's length should equal 0 but got %v", len(u.Memo)) + } } func TestRenderForm(t *testing.T) {