start refactoring forms. Allow list for recipe ingredients
This commit is contained in:
parent
349aa0dd5d
commit
74760707dd
|
@ -15,7 +15,7 @@ type RecipeMetaData struct {
|
|||
Title string `owl:"inputType=text"`
|
||||
Yield string `owl:"inputType=text"`
|
||||
Duration string `owl:"inputType=text"`
|
||||
Ingredients []string `owl:"inputType=text widget=textarea"`
|
||||
Ingredients []string `owl:"inputType=text widget=textlist"`
|
||||
Content string `owl:"inputType=text widget=textarea"`
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
<small>
|
||||
{{ if .MetaData.Yield }}
|
||||
Servings: <span class="p-yield">{{ .MetaData.Yield }}</span>
|
||||
{{ if .MetaData.Duration }}, {{end}}
|
||||
|
||||
{{ end }}
|
||||
|
||||
{{ if .MetaData.Duration }}
|
||||
Prep Time: <time class="dt-duration" value="{{ .MetaData.Duration }}">
|
||||
{{ .MetaData.Duration }}
|
||||
</time>
|
||||
{{ end }}
|
||||
</small>
|
||||
<br> <br>
|
||||
|
||||
<h2>Ingredients</h2>
|
||||
|
||||
<ul>
|
||||
{{ range $ingredient := .MetaData.Ingredients }}
|
||||
<li class="p-ingredient">
|
||||
{{ $ingredient }}
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
|
||||
<h2>Instructions</h2>
|
||||
{{.MetaData.Content | markdown }}
|
|
@ -32,7 +32,7 @@ type FormFieldParams struct {
|
|||
|
||||
type FormField struct {
|
||||
Name string
|
||||
Value string
|
||||
Value reflect.Value
|
||||
Params FormFieldParams
|
||||
}
|
||||
|
||||
|
@ -55,18 +55,30 @@ func (s *FormFieldParams) ApplyTag(tagKey string, tagValue string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *FormField) ToWidget() Widget {
|
||||
switch s.Params.Widget {
|
||||
case "textarea":
|
||||
return &TextareaWidget{*s}
|
||||
case "textlist":
|
||||
return &TextListWidget{*s}
|
||||
default:
|
||||
return &TextWidget{*s}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *FormField) Html() string {
|
||||
html := ""
|
||||
html += fmt.Sprintf("<label for=\"%v\">%v</label>\n", s.Name, s.Name)
|
||||
if s.Params.InputType == "text" && s.Params.Widget == "textarea" {
|
||||
html += fmt.Sprintf("<textarea name=\"%v\" id=\"%v\" rows=\"20\">%v</textarea>\n", s.Name, s.Name, s.Value)
|
||||
} else {
|
||||
if s.Params.InputType == "file" {
|
||||
html += fmt.Sprintf("<input type=\"%v\" name=\"%v\" id=\"%v\" value=\"%v\" />\n", s.Params.InputType, s.Name, s.Name, s.Value)
|
||||
} else {
|
||||
html += s.ToWidget().Html()
|
||||
html += "\n"
|
||||
}
|
||||
return html
|
||||
}
|
||||
|
||||
func FieldToFormField(field reflect.StructField, value string) (FormField, error) {
|
||||
func FieldToFormField(field reflect.StructField, value reflect.Value) (FormField, error) {
|
||||
formField := FormField{
|
||||
Name: field.Name,
|
||||
Value: value,
|
||||
|
@ -92,7 +104,10 @@ func StructToFormFields(data interface{}) ([]FormField, error) {
|
|||
numFields := dataType.NumField()
|
||||
fields := []FormField{}
|
||||
for i := 0; i < numFields; i++ {
|
||||
field, err := FieldToFormField(dataType.Field(i), dataValue.FieldByIndex([]int{i}).String())
|
||||
field, err := FieldToFormField(
|
||||
dataType.Field(i),
|
||||
dataValue.FieldByIndex([]int{i}),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -134,10 +149,10 @@ func (s *Form) Parse(ctx HttpFormData) (interface{}, error) {
|
|||
file, err := ctx.FormFile(fieldName)
|
||||
if err != nil {
|
||||
// If field already has a value, we can ignore the error
|
||||
if field.Value != "" {
|
||||
if field.Value != reflect.Zero(field.Value.Type()) {
|
||||
metaField := dataVal.Elem().FieldByName(fieldName)
|
||||
if metaField.IsValid() {
|
||||
metaField.SetString(field.Value)
|
||||
metaField.SetString(field.Value.String())
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
@ -167,7 +182,7 @@ func (s *Form) Parse(ctx HttpFormData) (interface{}, error) {
|
|||
formValue := ctx.FormValue(fieldName)
|
||||
metaField := dataVal.Elem().FieldByName(fieldName)
|
||||
if metaField.IsValid() {
|
||||
metaField.SetString(formValue)
|
||||
field.ToWidget().ParseValue(formValue, metaField)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
package forms
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Widget interface {
|
||||
Html() string
|
||||
ParseValue(value string, output reflect.Value) error
|
||||
}
|
||||
|
||||
type TextWidget struct {
|
||||
FormField
|
||||
}
|
||||
|
||||
func (s *TextWidget) Html() string {
|
||||
html := ""
|
||||
html += fmt.Sprintf("<input type=\"text\" name=\"%v\" value=\"%v\">\n", s.Name, s.Value.String())
|
||||
return html
|
||||
}
|
||||
|
||||
func (s *TextWidget) ParseValue(value string, output reflect.Value) error {
|
||||
output.SetString(value)
|
||||
return nil
|
||||
}
|
||||
|
||||
type TextareaWidget struct {
|
||||
FormField
|
||||
}
|
||||
|
||||
func (s *TextareaWidget) Html() string {
|
||||
html := ""
|
||||
html += fmt.Sprintf("<textarea name=\"%v\" rows=\"20\">%v</textarea>\n", s.Name, s.Value.String())
|
||||
return html
|
||||
}
|
||||
|
||||
func (s *TextareaWidget) ParseValue(value string, output reflect.Value) error {
|
||||
output.SetString(value)
|
||||
return nil
|
||||
}
|
||||
|
||||
type TextListWidget struct {
|
||||
FormField
|
||||
}
|
||||
|
||||
func (s *TextListWidget) Html() string {
|
||||
valueList := s.Value.Interface().([]string)
|
||||
value := strings.Join(valueList, "\n")
|
||||
|
||||
html := ""
|
||||
html += fmt.Sprintf("<textarea name=\"%v\" rows=\"20\">%v</textarea>\n", s.Name, value)
|
||||
return html
|
||||
}
|
||||
|
||||
func (s *TextListWidget) ParseValue(value string, output reflect.Value) error {
|
||||
list := strings.Split(value, "\n")
|
||||
// trim entries
|
||||
for i, item := range list {
|
||||
list[i] = strings.TrimSpace(item)
|
||||
}
|
||||
// remove empty entries
|
||||
for i := len(list) - 1; i >= 0; i-- {
|
||||
if list[i] == "" {
|
||||
list = append(list[:i], list[i+1:]...)
|
||||
}
|
||||
}
|
||||
|
||||
output.Set(reflect.ValueOf(list))
|
||||
return nil
|
||||
}
|
Loading…
Reference in New Issue