diff --git a/template.go b/template.go
index 6df25fd9..0feffbe3 100644
--- a/template.go
+++ b/template.go
@@ -31,6 +31,7 @@ func init() {
beegoTplFuncMap["str2html"] = Str2html
beegoTplFuncMap["htmlquote"] = Htmlquote
beegoTplFuncMap["htmlunquote"] = Htmlunquote
+ beegoTplFuncMap["renderform"] = RenderForm
}
// AddFuncMap let user to register a func in the template
diff --git a/utils.go b/utils.go
index e0ead258..0afcb4ba 100644
--- a/utils.go
+++ b/utils.go
@@ -178,7 +178,7 @@ func inSlice(v string, sl []string) bool {
func ParseForm(form url.Values, obj interface{}) error {
objT := reflect.TypeOf(obj)
objV := reflect.ValueOf(obj)
- if !(objT.Kind() == reflect.Ptr && objT.Elem().Kind() == reflect.Struct) {
+ if !isStructPtr(objT) {
return fmt.Errorf("%v must be a struct pointer", obj)
}
objT = objT.Elem()
@@ -189,8 +189,8 @@ func ParseForm(form url.Values, obj interface{}) error {
if !fieldV.CanSet() {
continue
}
- fieldT := objT.Field(i)
+ fieldT := objT.Field(i)
tags := strings.Split(fieldT.Tag.Get("form"), ",")
var tag string
if len(tags) == 0 || len(tags[0]) == 0 {
@@ -238,6 +238,69 @@ func ParseForm(form url.Values, obj interface{}) error {
return nil
}
+// form types for RenderForm function
+var FormType = map[string]bool{
+ "text": true,
+ "textarea": true,
+ "hidden": true,
+ "password": true,
+}
+
+var unKind = map[reflect.Kind]bool{
+ reflect.Uintptr: true,
+ reflect.Complex64: true,
+ reflect.Complex128: true,
+ reflect.Array: true,
+ reflect.Chan: true,
+ reflect.Func: true,
+ reflect.Map: true,
+ reflect.Ptr: true,
+ reflect.Slice: true,
+ reflect.Struct: true,
+ reflect.UnsafePointer: true,
+}
+
+// obj must be a struct pointer
+func RenderForm(obj interface{}) template.HTML {
+ objT := reflect.TypeOf(obj)
+ objV := reflect.ValueOf(obj)
+ if !isStructPtr(objT) {
+ return template.HTML("")
+ }
+ objT = objT.Elem()
+ objV = objV.Elem()
+
+ var raw []string
+ for i := 0; i < objT.NumField(); i++ {
+ fieldV := objV.Field(i)
+ if !fieldV.CanSet() || unKind[fieldV.Kind()] {
+ continue
+ }
+
+ fieldT := objT.Field(i)
+ tags := strings.Split(fieldT.Tag.Get("form"), ",")
+ name := fieldT.Name
+ if len(tags) < 2 {
+ if len(tags) == 1 && len(tags[0]) > 0 {
+ name = tags[0]
+ }
+ raw = append(raw, fmt.Sprintf(`%v: `,
+ fieldT.Name, name, fieldV.Interface()))
+ } else {
+ if len(tags[0]) > 0 {
+ name = tags[0]
+ }
+ raw = append(raw, fmt.Sprintf(`%v: `,
+ fieldT.Name, name, tags[1], fieldV.Interface()))
+ }
+ }
+ return template.HTML(strings.Join(raw, ""))
+}
+
+func isStructPtr(t reflect.Type) bool {
+ return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct
+}
+
func stringsToJson(str string) string {
rs := []rune(str)
jsons := ""
diff --git a/utils_test.go b/utils_test.go
index 405c939c..994846fe 100644
--- a/utils_test.go
+++ b/utils_test.go
@@ -1,6 +1,7 @@
package beego
import (
+ "html/template"
"net/url"
"testing"
"time"
@@ -144,3 +145,29 @@ func TestParseForm(t *testing.T) {
t.Errorf("Intro should equal `I am an engineer!` but got `%v`", u.Intro)
}
}
+
+func TestRenderForm(t *testing.T) {
+ type user struct {
+ Id int
+ tag string `form:tag`
+ Name interface{} `form:"username"`
+ Age int `form:"age,text"`
+ Email []string
+ Intro string `form:",textarea"`
+ }
+
+ u := user{Name: "test"}
+ output := RenderForm(u)
+ if output != template.HTML("") {
+ t.Errorf("output should be empty but got %v", output)
+ }
+ output = RenderForm(&u)
+ result := template.HTML(
+ `Id: ` +
+ `Name: ` +
+ `Age: ` +
+ `Intro: `)
+ if output != result {
+ t.Errorf("output should equal `%v` but got `%v`", result, output)
+ }
+}