Skip to content

Commit

Permalink
add option to pass dict style params down the line
Browse files Browse the repository at this point in the history
  • Loading branch information
donseba committed Aug 9, 2023
1 parent be342f6 commit a0600e6
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 15 deletions.
16 changes: 8 additions & 8 deletions example/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@ import (
)

var inputTpl = `<div>
<label {{with .Id}}for="{{.}}"{{end}} class="block text-sm font-medium text-gray-700">{{.Label}}{{ if eq .Required true }}*{{end}}</label>
<label {{with .Field.Id}}for="{{.}}"{{end}} class="block text-sm font-medium text-gray-700">{{.Field.Label}}{{ if eq .Field.Required true }}*{{end}}</label>
<div class="mt-1">
{{ if eq .Type "dropdown" }}
<select {{with .Id}}id="{{.}}"{{end}} name="{{.Name}}" class="bg-white block w-full rounded-md border border-gray-300 px-3 py-2 shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-indigo-500 sm:text-sm">
{{ $value := .Value }}
{{ range $k, $option := .Values }}
{{ if eq .Field.Type "dropdown" }}
<select {{with .Field.Id}}id="{{.}}"{{end}} name="{{.Field.Name}}" class="bg-white block w-full rounded-md border border-gray-300 px-3 py-2 shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-indigo-500 sm:text-sm">
{{ $value := .Field.Value }}
{{ range $k, $option := .Field.Values }}
<option value="{{$option.Value}}" {{ if eq $value $option.Value }}selected{{ end }} {{ if eq $option.Disabled true }}disabled{{ end }}>{{$option.Name}}</option>
{{ end }}
</select>
{{ else if eq .Type "checkbox" }}
<input {{with .Id}}id="{{.}}"{{end}} name="{{.Name}}" type="checkbox" {{ if eq .Required true }}required{{end}} {{ if eq .Value true }}checked{{end}} class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
{{ else if eq .Field.Type "checkbox" }}
<input {{with .Field.Id}}id="{{.}}"{{end}} name="{{.Field.Name}}" type="checkbox" {{ if eq .Required true }}required{{end}} {{ if eq .Field.Value true }}checked{{end}} class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
{{ else }}
<input {{with .Id}}id="{{.}}"{{end}} name="{{.Name}}" placeholder="{{.Placeholder}}" {{with .Value}}value="{{.}}"{{end}} {{ if eq .Required true }}required{{end}} class="block w-full appearance-none rounded-md border border-gray-300 px-3 py-2 placeholder-gray-400 shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-indigo-500 sm:text-sm">
<input {{with .Field.Id}}id="{{.}}"{{end}} name="{{.Field.Name}}" placeholder="{{.Field.Placeholder}}" {{with .Field.Value}}value="{{.}}"{{end}} {{ if eq .Required true }}required{{end}} class="block w-full appearance-none rounded-md border border-gray-300 px-3 py-2 placeholder-gray-400 shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-indigo-500 sm:text-sm">
{{ end }}
{{range errors}}
<span class="text-sm text-red-600">{{.}}</span>
Expand Down
46 changes: 40 additions & 6 deletions form.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package form

import (
"errors"
"html/template"
"strings"
)
Expand All @@ -23,14 +24,29 @@ func (f *Form) FuncMap() template.FuncMap {
}
}

func (f *Form) formRender(v interface{}, errs []FieldError) (template.HTML, error) {
func (f *Form) formRender(v interface{}, errs []FieldError, kv ...any) (template.HTML, error) {
tr, err := NewTransformer(v)
if err != nil {
return "", err
}

fieldErrors := scanError(errs)

var data = make(map[string]any)
if len(kv) > 0 {
if len(kv)%2 != 0 {
return "", errors.New("invalid dict call")
}

for i := 0; i < len(kv); i += 2 {
key, ok := kv[i].(string)
if !ok {
return "", errors.New("dict keys must be strings")
}
data[key] = kv[i+1]
}
}

var html template.HTML
for _, field := range tr.Fields {
if field.Type == FieldTypeGroup {
Expand All @@ -45,7 +61,10 @@ func (f *Form) formRender(v interface{}, errs []FieldError) (template.HTML, erro
var subhtml template.HTML

for _, subField := range field.Fields {
fieldhtml, err := f.formFieldHTML(subField, fieldErrors)
fMap := copyMap(data)
fMap["Field"] = field

fieldhtml, err := f.formFieldHTML(subField, fieldErrors, fMap)
if err != nil {
continue
}
Expand All @@ -57,7 +76,10 @@ func (f *Form) formRender(v interface{}, errs []FieldError) (template.HTML, erro
},
})

err = gtpl.Execute(&sb, field)
fMap := copyMap(data)
fMap["Field"] = field

err = gtpl.Execute(&sb, fMap)
if err != nil {
return "", err
}
Expand All @@ -66,7 +88,7 @@ func (f *Form) formRender(v interface{}, errs []FieldError) (template.HTML, erro
continue
}

fieldHTML, err := f.formFieldHTML(field, fieldErrors)
fieldHTML, err := f.formFieldHTML(field, fieldErrors, data)
if err != nil {
return "", err
}
Expand All @@ -76,7 +98,7 @@ func (f *Form) formRender(v interface{}, errs []FieldError) (template.HTML, erro
return html, nil
}

func (f *Form) formFieldHTML(field FormField, errors map[string][]string) (template.HTML, error) {
func (f *Form) formFieldHTML(field FormField, errors map[string][]string, data map[string]any) (template.HTML, error) {
tpl, err := f.template.Clone()
if err != nil {
return "", err
Expand All @@ -91,7 +113,11 @@ func (f *Form) formFieldHTML(field FormField, errors map[string][]string) (templ
return nil
},
})
err = tpl.Execute(&sb, field)

fMap := copyMap(data)
fMap["Field"] = field

err = tpl.Execute(&sb, fMap)
if err != nil {
return "", err
}
Expand All @@ -111,3 +137,11 @@ func scanError(errs []FieldError) map[string][]string {
}
return ret
}

func copyMap[K, V comparable](m map[K]V) map[K]V {
result := make(map[K]V)
for k, v := range m {
result[k] = v
}
return result
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module github.com/donseba/go-form

go 1.19
go 1.20

0 comments on commit a0600e6

Please sign in to comment.