func unWindStructure(m interface{}, baseName string) ([]interface{}, string) { t := reflect.TypeOf(m) v := reflect.ValueOf(m) if t.Kind() == reflect.Ptr { t = t.Elem() v = v.Elem() } fieldList := make([]interface{}, 0) fieldSort := "" fieldSetList := make(map[string]*FieldSetType, 0) fieldSetSort := make(map[string]string, 0) for i := 0; i < t.NumField(); i++ { options := make(map[string]struct{}) tag, tagf := formcommon.Tag(t, t.Field(i), "form_options") if tag != "" { var optionsArr []string = make([]string, 0) if tagf != nil { cached := tagf.GetParsed("form_options", func() interface{} { return strings.Split(formcommon.TagVal(t, i, "form_options"), ";") }) optionsArr = cached.([]string) } for _, opt := range optionsArr { if opt != "" { options[opt] = struct{}{} } } } if _, ok := options["-"]; !ok { widget := formcommon.TagVal(t, i, "form_widget") var f fields.FieldInterface var fName string if baseName == "" { fName = t.Field(i).Name } else { fName = strings.Join([]string{baseName, t.Field(i).Name}, ".") } //fmt.Println(fName, t.Field(i).Type.String(), t.Field(i).Type.Kind()) switch widget { case "color", "email", "file", "image", "month", "search", "tel", "url", "week": f = fields.TextFieldFromInstance(v, t, i, fName, widget) case "text": f = fields.TextFieldFromInstance(v, t, i, fName) case "hidden": f = fields.HiddenFieldFromInstance(v, t, i, fName) case "textarea": f = fields.TextAreaFieldFromInstance(v, t, i, fName) case "password": f = fields.PasswordFieldFromInstance(v, t, i, fName) case "select": f = fields.SelectFieldFromInstance(v, t, i, fName, options) case "date": f = fields.DateFieldFromInstance(v, t, i, fName) case "datetime": f = fields.DatetimeFieldFromInstance(v, t, i, fName) case "time": f = fields.TimeFieldFromInstance(v, t, i, fName) case "number": f = fields.NumberFieldFromInstance(v, t, i, fName) case "range": f = fields.RangeFieldFromInstance(v, t, i, fName) case "radio": f = fields.RadioFieldFromInstance(v, t, i, fName) case "checkbox": f = fields.CheckboxFieldFromInstance(v, t, i, fName) case "static": f = fields.StaticFieldFromInstance(v, t, i, fName) default: switch t.Field(i).Type.String() { case "string": f = fields.TextFieldFromInstance(v, t, i, fName) case "bool": f = fields.CheckboxFromInstance(v, t, i, fName, options) case "time.Time": f = fields.DatetimeFieldFromInstance(v, t, i, fName) case "int", "int64": f = fields.NumberFieldFromInstance(v, t, i, fName) case "float", "float64": f = fields.NumberFieldFromInstance(v, t, i, fName) case "struct": fl, fs := unWindStructure(v.Field(i).Interface(), fName) if fs != "" { if fieldSort == "" { fieldSort = fs } else { fieldSort += "," + fs } } fieldList = append(fieldList, fl...) f = nil default: if t.Field(i).Type.Kind() == reflect.Struct || (t.Field(i).Type.Kind() == reflect.Ptr && t.Field(i).Type.Elem().Kind() == reflect.Struct) { fl, fs := unWindStructure(v.Field(i).Interface(), fName) if fs != "" { if fieldSort == "" { fieldSort = fs } else { fieldSort += "," + fs } } fieldList = append(fieldList, fl...) f = nil } else { f = fields.TextFieldFromInstance(v, t, i, fName) } } } if f != nil { label := formcommon.TagVal(t, i, "form_label") if label == "" { label = strings.Title(t.Field(i).Name) } label = formcommon.LabelFn(label) f.SetLabel(label) params := formcommon.TagVal(t, i, "form_params") if params != "" { if paramsMap, err := url.ParseQuery(params); err == nil { for k, v := range paramsMap { if k == "placeholder" || k == "title" { v[0] = formcommon.LabelFn(v[0]) } f.SetParam(k, v[0]) } } else { fmt.Println(err) } } valid := formcommon.TagVal(t, i, "valid") if valid != "" { ValidTagFn(valid, f) } fieldset := formcommon.TagVal(t, i, "form_fieldset") fieldsort := formcommon.TagVal(t, i, "form_sort") if fieldset != "" { fieldset = formcommon.LabelFn(fieldset) f.SetData("container", "fieldset") if _, ok := fieldSetList[fieldset]; !ok { fieldSetList[fieldset] = FieldSet(fieldset, f) } else { fieldSetList[fieldset].Elements(f) } if fieldsort != "" { if _, ok := fieldSetSort[fieldset]; !ok { fieldSetSort[fieldset] = fName + ":" + fieldsort } else { fieldSetSort[fieldset] += "," + fName + ":" + fieldsort } } } else { fieldList = append(fieldList, f) if fieldsort != "" { if fieldSort == "" { fieldSort = fName + ":" + fieldsort } else { fieldSort += "," + fName + ":" + fieldsort } } } } } } for _, v := range fieldSetList { if s, ok := fieldSetSort[v.Name()]; ok { v.Sort(s) } fieldList = append(fieldList, v) } return fieldList, fieldSort }