Add renderform template function
Showing
3 changed files
with
93 additions
and
2 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,8 +189,8 @@ func ParseForm(form url.Values, obj interface{}) error { | ... | @@ -189,8 +189,8 @@ func ParseForm(form url.Values, obj interface{}) error { |
| 189 | if !fieldV.CanSet() { | 189 | if !fieldV.CanSet() { |
| 190 | continue | 190 | continue |
| 191 | } | 191 | } |
| 192 | fieldT := objT.Field(i) | ||
| 193 | 192 | ||
| 193 | fieldT := objT.Field(i) | ||
| 194 | tags := strings.Split(fieldT.Tag.Get("form"), ",") | 194 | tags := strings.Split(fieldT.Tag.Get("form"), ",") |
| 195 | var tag string | 195 | var tag string |
| 196 | if len(tags) == 0 || len(tags[0]) == 0 { | 196 | if len(tags) == 0 || len(tags[0]) == 0 { |
| ... | @@ -238,6 +238,69 @@ func ParseForm(form url.Values, obj interface{}) error { | ... | @@ -238,6 +238,69 @@ func ParseForm(form url.Values, obj interface{}) error { |
| 238 | return nil | 238 | return nil |
| 239 | } | 239 | } |
| 240 | 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 | |||
| 241 | func stringsToJson(str string) string { | 304 | func stringsToJson(str string) string { |
| 242 | rs := []rune(str) | 305 | rs := []rune(str) |
| 243 | 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" |
| ... | @@ -144,3 +145,29 @@ func TestParseForm(t *testing.T) { | ... | @@ -144,3 +145,29 @@ func TestParseForm(t *testing.T) { |
| 144 | t.Errorf("Intro should equal `I am an engineer!` but got `%v`", u.Intro) | 145 | t.Errorf("Intro should equal `I am an engineer!` but got `%v`", u.Intro) |
| 145 | } | 146 | } |
| 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) | ||
| 172 | } | ||
| 173 | } | ... | ... |
-
Please register or sign in to post a comment