Merge pull request #143 from miraclesu/form
Add renderform template function
Showing
3 changed files
with
110 additions
and
9 deletions
| ... | @@ -31,6 +31,7 @@ func init() { | ... | @@ -31,6 +31,7 @@ func init() { |
| 31 | beegoTplFuncMap["str2html"] = Str2html | 31 | beegoTplFuncMap["str2html"] = Str2html |
| 32 | beegoTplFuncMap["htmlquote"] = Htmlquote | 32 | beegoTplFuncMap["htmlquote"] = Htmlquote |
| 33 | beegoTplFuncMap["htmlunquote"] = Htmlunquote | 33 | beegoTplFuncMap["htmlunquote"] = Htmlunquote |
| 34 | beegoTplFuncMap["renderform"] = RenderForm | ||
| 34 | } | 35 | } |
| 35 | 36 | ||
| 36 | // AddFuncMap let user to register a func in the template | 37 | // AddFuncMap let user to register a func in the template | ... | ... |
| ... | @@ -178,7 +178,7 @@ func inSlice(v string, sl []string) bool { | ... | @@ -178,7 +178,7 @@ func inSlice(v string, sl []string) bool { |
| 178 | func ParseForm(form url.Values, obj interface{}) error { | 178 | func ParseForm(form url.Values, obj interface{}) error { |
| 179 | objT := reflect.TypeOf(obj) | 179 | objT := reflect.TypeOf(obj) |
| 180 | objV := reflect.ValueOf(obj) | 180 | objV := reflect.ValueOf(obj) |
| 181 | if !(objT.Kind() == reflect.Ptr && objT.Elem().Kind() == reflect.Struct) { | 181 | if !isStructPtr(objT) { |
| 182 | return fmt.Errorf("%v must be a struct pointer", obj) | 182 | return fmt.Errorf("%v must be a struct pointer", obj) |
| 183 | } | 183 | } |
| 184 | objT = objT.Elem() | 184 | objT = objT.Elem() |
| ... | @@ -189,11 +189,16 @@ func ParseForm(form url.Values, obj interface{}) error { | ... | @@ -189,11 +189,16 @@ func ParseForm(form url.Values, obj interface{}) error { |
| 189 | if !fieldV.CanSet() { | 189 | if !fieldV.CanSet() { |
| 190 | continue | 190 | continue |
| 191 | } | 191 | } |
| 192 | |||
| 192 | fieldT := objT.Field(i) | 193 | fieldT := objT.Field(i) |
| 193 | tag := fieldT.Tag.Get("form") | 194 | tags := strings.Split(fieldT.Tag.Get("form"), ",") |
| 194 | if len(tag) == 0 { | 195 | var tag string |
| 196 | if len(tags) == 0 || len(tags[0]) == 0 { | ||
| 195 | tag = fieldT.Name | 197 | tag = fieldT.Name |
| 198 | } else { | ||
| 199 | tag = tags[0] | ||
| 196 | } | 200 | } |
| 201 | |||
| 197 | value := form.Get(tag) | 202 | value := form.Get(tag) |
| 198 | if len(value) == 0 { | 203 | if len(value) == 0 { |
| 199 | continue | 204 | continue |
| ... | @@ -233,6 +238,69 @@ func ParseForm(form url.Values, obj interface{}) error { | ... | @@ -233,6 +238,69 @@ func ParseForm(form url.Values, obj interface{}) error { |
| 233 | return nil | 238 | return nil |
| 234 | } | 239 | } |
| 235 | 240 | ||
| 241 | // form types for RenderForm function | ||
| 242 | var FormType = map[string]bool{ | ||
| 243 | "text": true, | ||
| 244 | "textarea": true, | ||
| 245 | "hidden": true, | ||
| 246 | "password": true, | ||
| 247 | } | ||
| 248 | |||
| 249 | var unKind = map[reflect.Kind]bool{ | ||
| 250 | reflect.Uintptr: true, | ||
| 251 | reflect.Complex64: true, | ||
| 252 | reflect.Complex128: true, | ||
| 253 | reflect.Array: true, | ||
| 254 | reflect.Chan: true, | ||
| 255 | reflect.Func: true, | ||
| 256 | reflect.Map: true, | ||
| 257 | reflect.Ptr: true, | ||
| 258 | reflect.Slice: true, | ||
| 259 | reflect.Struct: true, | ||
| 260 | reflect.UnsafePointer: true, | ||
| 261 | } | ||
| 262 | |||
| 263 | // obj must be a struct pointer | ||
| 264 | func RenderForm(obj interface{}) template.HTML { | ||
| 265 | objT := reflect.TypeOf(obj) | ||
| 266 | objV := reflect.ValueOf(obj) | ||
| 267 | if !isStructPtr(objT) { | ||
| 268 | return template.HTML("") | ||
| 269 | } | ||
| 270 | objT = objT.Elem() | ||
| 271 | objV = objV.Elem() | ||
| 272 | |||
| 273 | var raw []string | ||
| 274 | for i := 0; i < objT.NumField(); i++ { | ||
| 275 | fieldV := objV.Field(i) | ||
| 276 | if !fieldV.CanSet() || unKind[fieldV.Kind()] { | ||
| 277 | continue | ||
| 278 | } | ||
| 279 | |||
| 280 | fieldT := objT.Field(i) | ||
| 281 | tags := strings.Split(fieldT.Tag.Get("form"), ",") | ||
| 282 | name := fieldT.Name | ||
| 283 | if len(tags) < 2 { | ||
| 284 | if len(tags) == 1 && len(tags[0]) > 0 { | ||
| 285 | name = tags[0] | ||
| 286 | } | ||
| 287 | raw = append(raw, fmt.Sprintf(`%v: <input name="%v" type="text" value="%v">`, | ||
| 288 | fieldT.Name, name, fieldV.Interface())) | ||
| 289 | } else { | ||
| 290 | if len(tags[0]) > 0 { | ||
| 291 | name = tags[0] | ||
| 292 | } | ||
| 293 | raw = append(raw, fmt.Sprintf(`%v: <input name="%v" type="%v" value="%v">`, | ||
| 294 | fieldT.Name, name, tags[1], fieldV.Interface())) | ||
| 295 | } | ||
| 296 | } | ||
| 297 | return template.HTML(strings.Join(raw, "</br>")) | ||
| 298 | } | ||
| 299 | |||
| 300 | func isStructPtr(t reflect.Type) bool { | ||
| 301 | return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct | ||
| 302 | } | ||
| 303 | |||
| 236 | func stringsToJson(str string) string { | 304 | func stringsToJson(str string) string { |
| 237 | rs := []rune(str) | 305 | rs := []rune(str) |
| 238 | jsons := "" | 306 | jsons := "" | ... | ... |
| 1 | package beego | 1 | package beego |
| 2 | 2 | ||
| 3 | import ( | 3 | import ( |
| 4 | "html/template" | ||
| 4 | "net/url" | 5 | "net/url" |
| 5 | "testing" | 6 | "testing" |
| 6 | "time" | 7 | "time" |
| ... | @@ -106,8 +107,9 @@ func TestParseForm(t *testing.T) { | ... | @@ -106,8 +107,9 @@ func TestParseForm(t *testing.T) { |
| 106 | Id int | 107 | Id int |
| 107 | tag string `form:tag` | 108 | tag string `form:tag` |
| 108 | Name interface{} `form:"username"` | 109 | Name interface{} `form:"username"` |
| 109 | Age int `form:"age"` | 110 | Age int `form:"age,text"` |
| 110 | Email string | 111 | Email string |
| 112 | Intro string `form:",textarea"` | ||
| 111 | } | 113 | } |
| 112 | 114 | ||
| 113 | u := user{} | 115 | u := user{} |
| ... | @@ -116,6 +118,7 @@ func TestParseForm(t *testing.T) { | ... | @@ -116,6 +118,7 @@ func TestParseForm(t *testing.T) { |
| 116 | "username": []string{"test"}, | 118 | "username": []string{"test"}, |
| 117 | "age": []string{"40"}, | 119 | "age": []string{"40"}, |
| 118 | "Email": []string{"test@gmail.com"}, | 120 | "Email": []string{"test@gmail.com"}, |
| 121 | "Intro": []string{"I am an engineer!"}, | ||
| 119 | } | 122 | } |
| 120 | if err := ParseForm(form, u); err == nil { | 123 | if err := ParseForm(form, u); err == nil { |
| 121 | t.Fatal("nothing will be changed") | 124 | t.Fatal("nothing will be changed") |
| ... | @@ -124,18 +127,47 @@ func TestParseForm(t *testing.T) { | ... | @@ -124,18 +127,47 @@ func TestParseForm(t *testing.T) { |
| 124 | t.Fatal(err) | 127 | t.Fatal(err) |
| 125 | } | 128 | } |
| 126 | if u.Id != 0 { | 129 | if u.Id != 0 { |
| 127 | t.Error("Id should not be changed") | 130 | t.Errorf("Id should equal 0 but got %v", u.Id) |
| 128 | } | 131 | } |
| 129 | if len(u.tag) != 0 { | 132 | if len(u.tag) != 0 { |
| 130 | t.Error("tag should not be changed") | 133 | t.Errorf("tag's length should equal 0 but got %v", len(u.tag)) |
| 131 | } | 134 | } |
| 132 | if u.Name.(string) != "test" { | 135 | if u.Name.(string) != "test" { |
| 133 | t.Error("should be equal") | 136 | t.Errorf("Name should equal `test` but got `%v`", u.Name.(string)) |
| 134 | } | 137 | } |
| 135 | if u.Age != 40 { | 138 | if u.Age != 40 { |
| 136 | t.Error("should be equal") | 139 | t.Errorf("Age should equal 40 but got %v", u.Age) |
| 137 | } | 140 | } |
| 138 | if u.Email != "test@gmail.com" { | 141 | if u.Email != "test@gmail.com" { |
| 139 | t.Error("should be equal") | 142 | t.Errorf("Email should equal `test@gmail.com` but got `%v`", u.Email) |
| 143 | } | ||
| 144 | if u.Intro != "I am an engineer!" { | ||
| 145 | t.Errorf("Intro should equal `I am an engineer!` but got `%v`", u.Intro) | ||
| 146 | } | ||
| 147 | } | ||
| 148 | |||
| 149 | func TestRenderForm(t *testing.T) { | ||
| 150 | type user struct { | ||
| 151 | Id int | ||
| 152 | tag string `form:tag` | ||
| 153 | Name interface{} `form:"username"` | ||
| 154 | Age int `form:"age,text"` | ||
| 155 | Email []string | ||
| 156 | Intro string `form:",textarea"` | ||
| 157 | } | ||
| 158 | |||
| 159 | u := user{Name: "test"} | ||
| 160 | output := RenderForm(u) | ||
| 161 | if output != template.HTML("") { | ||
| 162 | t.Errorf("output should be empty but got %v", output) | ||
| 163 | } | ||
| 164 | output = RenderForm(&u) | ||
| 165 | result := template.HTML( | ||
| 166 | `Id: <input name="Id" type="text" value="0"></br>` + | ||
| 167 | `Name: <input name="username" type="text" value="test"></br>` + | ||
| 168 | `Age: <input name="age" type="text" value="0"></br>` + | ||
| 169 | `Intro: <input name="Intro" type="textarea" value="">`) | ||
| 170 | if output != result { | ||
| 171 | t.Errorf("output should equal `%v` but got `%v`", result, output) | ||
| 140 | } | 172 | } |
| 141 | } | 173 | } | ... | ... |
-
Please register or sign in to post a comment