forked from kirves/go-form-it
-
Notifications
You must be signed in to change notification settings - Fork 0
/
options.go
138 lines (119 loc) · 4.74 KB
/
options.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package fields
import (
"fmt"
"reflect"
"strings"
"github.com/bkrn/go-form-it/common"
)
// Id - Value pair used to define an option for select and redio input fields.
type InputChoice struct {
Id, Val string
}
// // Radio button type.
// type RadioType struct {
// Field
// }
// // Select field type.
// type SelectType struct {
// Field
// }
// // Checkbox field type.
// type CheckBoxType struct {
// Field
// }
// =============== RADIO
// RadioField creates a default radio button input field with the provided name and list of choices.
func RadioField(name string, choices []InputChoice) *Field {
ret := FieldWithType(name, formcommon.RADIO)
ret.additionalData["choices"] = []InputChoice{}
ret.SetRadioChoices(choices)
return ret
}
// RadioFieldFromInstance creates and initializes a radio field based on its name, the reference object instance and field number.
// This method looks for "form_choices" and "form_value" tags to add additional parameters to the field. "form_choices" tag is a list
// of <id>|<value> options, joined by "|" character; ex: "A|Option A|B|Option B" translates into 2 options: <A, Option A> and <B, Option B>.
// It also uses i object's [fieldNo]-th field content (if any) to override the "form_value" option and fill the HTML field.
func RadioFieldFromInstance(i interface{}, fieldNo int, name string) *Field {
t := reflect.TypeOf(i).Field(fieldNo).Tag
choices := strings.Split(t.Get("form_choices"), "|")
chArr := make([]InputChoice, 0)
chMap := make(map[string]string)
for i := 0; i < len(choices)-1; i += 2 {
chArr = append(chArr, InputChoice{choices[i], choices[i+1]})
chMap[choices[i]] = choices[i+1]
}
ret := RadioField(name, chArr)
var v string = t.Get("form_value")
if v == "" {
v = fmt.Sprintf("%s", reflect.ValueOf(i).Field(fieldNo).String())
}
if _, ok := chMap[v]; ok {
ret.SetValue(v)
}
return ret
}
// ================ SELECT
// SelectField creates a default select input field with the provided name and map of choices. Choices for SelectField are grouped
// by name (if <optgroup> is needed); "" group is the default one and does not trigger a <optgroup></optgroup> rendering.
func SelectField(name string, choices map[string][]InputChoice) *Field {
ret := FieldWithType(name, formcommon.SELECT)
ret.additionalData["choices"] = map[string][]InputChoice{}
ret.additionalData["multValues"] = map[string]struct{}{}
ret.SetSelectChoices(choices)
return ret
}
// SelectFieldFromInstance creates and initializes a select field based on its name, the reference object instance and field number.
// This method looks for "form_choices" and "form_value" tags to add additional parameters to the field. "form_choices" tag is a list
// of <group<|<id>|<value> options, joined by "|" character; ex: "G1|A|Option A|G1|B|Option B" translates into 2 options in the same group G1:
// <A, Option A> and <B, Option B>. "" group is the default one.
// It also uses i object's [fieldNo]-th field content (if any) to override the "form_value" option and fill the HTML field.
func SelectFieldFromInstance(i interface{}, fieldNo int, name string, options map[string]struct{}) *Field {
t := reflect.TypeOf(i).Field(fieldNo).Tag
choices := strings.Split(t.Get("form_choices"), "|")
chArr := make(map[string][]InputChoice)
chMap := make(map[string]string)
for i := 0; i < len(choices)-2; i += 3 {
if _, ok := chArr[choices[i]]; !ok {
chArr[choices[i]] = make([]InputChoice, 0)
}
chArr[choices[i]] = append(chArr[choices[i]], InputChoice{choices[i+1], choices[i+2]})
chMap[choices[i+1]] = choices[i+2]
}
ret := SelectField(name, chArr)
if _, ok := options["multiple"]; ok {
ret.MultipleChoice()
}
var v string = fmt.Sprintf("%s", reflect.ValueOf(i).Field(fieldNo).String())
if v == "" {
// TODO: multiple value parsing
v = t.Get("form_value")
}
if _, ok := chMap[v]; ok {
ret.SetValue(v)
}
return ret
}
// ================== CHECKBOX
// Checkbox creates a default checkbox field with the provided name. It also makes it checked by default based
// on the checked parameter.
func Checkbox(name string, checked bool) *Field {
ret := FieldWithType(name, formcommon.CHECKBOX)
if checked {
ret.AddTag("checked")
}
return ret
}
// CheckboxFromInstance creates and initializes a checkbox field based on its name, the reference object instance, field number and field options.
// It uses i object's [fieldNo]-th field content (if any) to override the "checked" option in the options map and check the field.
func CheckboxFromInstance(i interface{}, fieldNo int, name string, options map[string]struct{}) *Field {
ret := FieldWithType(name, formcommon.CHECKBOX)
if _, ok := options["checked"]; ok {
ret.AddTag("checked")
} else {
val := reflect.ValueOf(i).Field(fieldNo).Bool()
if val {
ret.AddTag("checked")
}
}
return ret
}