From 0d3a806c238ebd9f37e5bc28d36037223480c980 Mon Sep 17 00:00:00 2001 From: Joshua Santos Date: Wed, 15 Jun 2016 17:17:50 -0700 Subject: [PATCH 1/6] Add meta fields with required flag --- templatefunc.go | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/templatefunc.go b/templatefunc.go index 8558733f..0f9af481 100644 --- a/templatefunc.go +++ b/templatefunc.go @@ -422,17 +422,18 @@ func RenderForm(obj interface{}) template.HTML { fieldT := objT.Field(i) label, name, fType, id, class, ignored := parseFormTag(fieldT) + required := parseMetaTag(fieldT) if ignored { continue } - raw = append(raw, renderFormField(label, name, fType, fieldV.Interface(), id, class)) + raw = append(raw, renderFormField(label, name, fType, fieldV.Interface(), id, class, required)) } return template.HTML(strings.Join(raw, "
")) } // renderFormField returns a string containing HTML of a single form field. -func renderFormField(label, name, fType string, value interface{}, id string, class string) string { +func renderFormField(label, name, fType string, value interface{}, id string, class string, required bool) string { if id != "" { id = " id=\"" + id + "\"" } @@ -441,8 +442,13 @@ func renderFormField(label, name, fType string, value interface{}, id string, cl class = " class=\"" + class + "\"" } + requiredString := "" + if required { + requiredString = " required" + } + if isValidForInput(fType) { - return fmt.Sprintf(`%v`, label, id, class, name, fType, value) + return fmt.Sprintf(`%v`, label, id, class, name, fType, value, requiredString) } return fmt.Sprintf(`%v<%v%v%v name="%v">%v`, label, fType, id, class, name, value, fType) @@ -496,6 +502,21 @@ func parseFormTag(fieldT reflect.StructField) (label, name, fType string, id str label = tags[2] } } + + return +} + +// parseMetaTag takes the stuct-tag of a StructField and parses the `meta` value. +// returned is the boolean of whether the field is required +func parseMetaTag(fieldT reflect.StructField) (required bool) { + meta := strings.Split(fieldT.Tag.Get("meta"), ",") + required = false + switch len(meta) { + case 1: + if len(meta[0]) > 0 && meta[0] != "-" { + required = true + } + } return } From f9f92b4f61709fc673e9c081cc4f5740a7b13d72 Mon Sep 17 00:00:00 2001 From: Joshua Santos Date: Tue, 28 Jun 2016 15:19:58 -0700 Subject: [PATCH 2/6] Merge meta tag into parseFormField --- templatefunc.go | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/templatefunc.go b/templatefunc.go index 0f9af481..827c9b6b 100644 --- a/templatefunc.go +++ b/templatefunc.go @@ -421,8 +421,7 @@ func RenderForm(obj interface{}) template.HTML { fieldT := objT.Field(i) - label, name, fType, id, class, ignored := parseFormTag(fieldT) - required := parseMetaTag(fieldT) + label, name, fType, id, class, ignored, required := parseFormTag(fieldT) if ignored { continue } @@ -467,7 +466,7 @@ func isValidForInput(fType string) bool { // parseFormTag takes the stuct-tag of a StructField and parses the `form` value. // returned are the form label, name-property, type and wether the field should be ignored. -func parseFormTag(fieldT reflect.StructField) (label, name, fType string, id string, class string, ignored bool) { +func parseFormTag(fieldT reflect.StructField) (label, name, fType string, id string, class string, ignored bool, required bool) { tags := strings.Split(fieldT.Tag.Get("form"), ",") label = fieldT.Name + ": " name = fieldT.Name @@ -476,6 +475,15 @@ func parseFormTag(fieldT reflect.StructField) (label, name, fType string, id str id = fieldT.Tag.Get("id") class = fieldT.Tag.Get("class") + meta := strings.Split(fieldT.Tag.Get("meta"), ",") + required = false + switch len(meta) { + case 1: + if len(meta[0]) > 0 && meta[0] != "-" { + required = true + } + } + switch len(tags) { case 1: if tags[0] == "-" { @@ -506,20 +514,6 @@ func parseFormTag(fieldT reflect.StructField) (label, name, fType string, id str return } -// parseMetaTag takes the stuct-tag of a StructField and parses the `meta` value. -// returned is the boolean of whether the field is required -func parseMetaTag(fieldT reflect.StructField) (required bool) { - meta := strings.Split(fieldT.Tag.Get("meta"), ",") - required = false - switch len(meta) { - case 1: - if len(meta[0]) > 0 && meta[0] != "-" { - required = true - } - } - return -} - func isStructPtr(t reflect.Type) bool { return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct } From 21c78216923d0a507d7f7740a931f495f8f31cc5 Mon Sep 17 00:00:00 2001 From: Joshua Santos Date: Tue, 28 Jun 2016 16:24:32 -0700 Subject: [PATCH 3/6] Add test function --- templatefunc_test.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/templatefunc_test.go b/templatefunc_test.go index 98fbf7ab..a4a2c237 100644 --- a/templatefunc_test.go +++ b/templatefunc_test.go @@ -195,15 +195,20 @@ func TestRenderForm(t *testing.T) { } func TestRenderFormField(t *testing.T) { - html := renderFormField("Label: ", "Name", "text", "Value", "", "") + html := renderFormField("Label: ", "Name", "text", "Value", "", "", false) if html != `Label: ` { t.Errorf("Wrong html output for input[type=text]: %v ", html) } - html = renderFormField("Label: ", "Name", "textarea", "Value", "", "") + html = renderFormField("Label: ", "Name", "textarea", "Value", "", "", false) if html != `Label: ` { t.Errorf("Wrong html output for textarea: %v ", html) } + + html = renderFormField("Label: ", "Name", "textarea", "Value", "", "", true) + if html != `Label: ` { + t.Errorf("Wrong html output for textarea: %v ", html) + } } func TestParseFormTag(t *testing.T) { From 8917fe44a91505457494631f267757b8b7e57508 Mon Sep 17 00:00:00 2001 From: Joshua Santos Date: Tue, 28 Jun 2016 16:31:45 -0700 Subject: [PATCH 4/6] Add test functions --- templatefunc_test.go | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/templatefunc_test.go b/templatefunc_test.go index a4a2c237..6f337928 100644 --- a/templatefunc_test.go +++ b/templatefunc_test.go @@ -219,35 +219,42 @@ func TestParseFormTag(t *testing.T) { OnlyLabel int `form:",,年龄:"` OnlyName int `form:"name" id:"name" class:"form-name"` Ignored int `form:"-"` + Required int `form:"name" meta:"true"` } objT := reflect.TypeOf(&user{}).Elem() - label, name, fType, id, class, ignored := parseFormTag(objT.Field(0)) + label, name, fType, id, class, ignored, required := parseFormTag(objT.Field(0)) if !(name == "name" && label == "年龄:" && fType == "text" && ignored == false) { t.Errorf("Form Tag with name, label and type was not correctly parsed.") } - label, name, fType, id, class, ignored = parseFormTag(objT.Field(1)) + label, name, fType, id, class, ignored, required = parseFormTag(objT.Field(1)) if !(name == "NoName" && label == "年龄:" && fType == "hidden" && ignored == false) { t.Errorf("Form Tag with label and type but without name was not correctly parsed.") } - label, name, fType, id, class, ignored = parseFormTag(objT.Field(2)) + label, name, fType, id, class, ignored, required = parseFormTag(objT.Field(2)) if !(name == "OnlyLabel" && label == "年龄:" && fType == "text" && ignored == false) { t.Errorf("Form Tag containing only label was not correctly parsed.") } - label, name, fType, id, class, ignored = parseFormTag(objT.Field(3)) + label, name, fType, id, class, ignored, required = parseFormTag(objT.Field(3)) if !(name == "name" && label == "OnlyName: " && fType == "text" && ignored == false && id == "name" && class == "form-name") { t.Errorf("Form Tag containing only name was not correctly parsed.") } - label, name, fType, id, class, ignored = parseFormTag(objT.Field(4)) + label, name, fType, id, class, ignored, required = parseFormTag(objT.Field(4)) if ignored == false { t.Errorf("Form Tag that should be ignored was not correctly parsed.") } + + label, name, fType, id, class, ignored, required = parseFormTag(objT.Field(5)) + if !(name == "name" && required == true) { + t.Errorf("Form Tag containing only name and required was not correctly parsed.") + } + } func TestMapGet(t *testing.T) { From 84b6bef7d064371365822d60928e163f54988b0d Mon Sep 17 00:00:00 2001 From: Joshua Santos Date: Tue, 28 Jun 2016 16:39:09 -0700 Subject: [PATCH 5/6] Required field useful for not only input --- templatefunc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templatefunc.go b/templatefunc.go index 827c9b6b..d6afaf15 100644 --- a/templatefunc.go +++ b/templatefunc.go @@ -450,7 +450,7 @@ func renderFormField(label, name, fType string, value interface{}, id string, cl return fmt.Sprintf(`%v`, label, id, class, name, fType, value, requiredString) } - return fmt.Sprintf(`%v<%v%v%v name="%v">%v`, label, fType, id, class, name, value, fType) + return fmt.Sprintf(`%v<%v%v%v name="%v"%v>%v`, label, fType, id, class, name, requiredString, value, fType) } // isValidForInput checks if fType is a valid value for the `type` property of an HTML input element. From e0393b721ced07de32ae3d57e20b1fcd214d97e6 Mon Sep 17 00:00:00 2001 From: Joshua Santos Date: Thu, 30 Jun 2016 10:32:53 -0700 Subject: [PATCH 6/6] Change meta to required, and refactor a bit to cover edge cases --- templatefunc.go | 9 +++------ templatefunc_test.go | 24 ++++++++++++++++++------ 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/templatefunc.go b/templatefunc.go index d6afaf15..36442984 100644 --- a/templatefunc.go +++ b/templatefunc.go @@ -475,13 +475,10 @@ func parseFormTag(fieldT reflect.StructField) (label, name, fType string, id str id = fieldT.Tag.Get("id") class = fieldT.Tag.Get("class") - meta := strings.Split(fieldT.Tag.Get("meta"), ",") required = false - switch len(meta) { - case 1: - if len(meta[0]) > 0 && meta[0] != "-" { - required = true - } + required_field := fieldT.Tag.Get("required") + if required_field != "-" && required_field != "" { + required, _ = strconv.ParseBool(required_field) } switch len(tags) { diff --git a/templatefunc_test.go b/templatefunc_test.go index 6f337928..86de37ae 100644 --- a/templatefunc_test.go +++ b/templatefunc_test.go @@ -214,12 +214,14 @@ func TestRenderFormField(t *testing.T) { func TestParseFormTag(t *testing.T) { // create struct to contain field with different types of struct-tag `form` type user struct { - All int `form:"name,text,年龄:"` - NoName int `form:",hidden,年龄:"` - OnlyLabel int `form:",,年龄:"` - OnlyName int `form:"name" id:"name" class:"form-name"` - Ignored int `form:"-"` - Required int `form:"name" meta:"true"` + All int `form:"name,text,年龄:"` + NoName int `form:",hidden,年龄:"` + OnlyLabel int `form:",,年龄:"` + OnlyName int `form:"name" id:"name" class:"form-name"` + Ignored int `form:"-"` + Required int `form:"name" required:"true"` + IgnoreRequired int `form:"name"` + NotRequired int `form:"name" required:"false"` } objT := reflect.TypeOf(&user{}).Elem() @@ -255,6 +257,16 @@ func TestParseFormTag(t *testing.T) { t.Errorf("Form Tag containing only name and required was not correctly parsed.") } + label, name, fType, id, class, ignored, required = parseFormTag(objT.Field(6)) + if !(name == "name" && required == false) { + t.Errorf("Form Tag containing only name and ignore required was not correctly parsed.") + } + + label, name, fType, id, class, ignored, required = parseFormTag(objT.Field(7)) + if !(name == "name" && required == false) { + t.Errorf("Form Tag containing only name and not required was not correctly parsed.") + } + } func TestMapGet(t *testing.T) {