Documentation ¶
Overview ¶
Package form provides utilities for iterating over go types and generating HTML forms.
By default this package is designed to work with other packages;
Decoding Form Values ¶
The gorilla/schema package is used to decode a submitted form back into Go types.
Custom naming schemes can be passed so other decoders are supported.
Rendering HTML ¶
The x/net/html package is used for rendering the HTML form data and keeping track of related information such as html.Attribute and the overall element tree.
Index ¶
- Constants
- Variables
- func DefaultArrayNamer(total string, index int) string
- func DefaultStructNamer(total, name string) string
- func EncodeBool(context *EncoderContext, typeOf reflect.Type, value reflect.Value) error
- func EncodeDateTime(context *EncoderContext, typeOf reflect.Type, value reflect.Value) error
- func EncodeFloat64(context *EncoderContext, typeOf reflect.Type, value reflect.Value) error
- func EncodeInt(context *EncoderContext, typeOf reflect.Type, value reflect.Value) error
- func EncodeString(context *EncoderContext, typeOf reflect.Type, value reflect.Value) error
- func EncodeUint(context *EncoderContext, typeOf reflect.Type, value reflect.Value) error
- func NodeDeleteAttr(node *html.Node, key string)
- func NodeGetAttr(node *html.Node, key string) (html.Attribute, bool)
- func NodeHasAttr(node *html.Node, key string) (int, bool)
- func NodeSetAttr(node *html.Node, key string, value string, setmode SetMode)
- func ParseTag(tag string) map[string]string
- func SetValidRange(node *html.Node, value reflect.Value)
- type ArrayEncoder
- type ArrayNamingScheme
- type AttributeWrapper
- type CustomEncoder
- type CustomEncoderFunc
- type Encoder
- func (encoder *Encoder) AppendWrappers(wrappers ...CustomEncoder)
- func (encoder *Encoder) Encode(context *EncoderContext, typeOf reflect.Type, valueOf reflect.Value) error
- func (encoder *Encoder) EncodeValue(parent *html.Node, v interface{}) error
- func (encoder *Encoder) RegisterKindEncoder(kind reflect.Kind, custom_encoder CustomEncoder)
- func (encoder *Encoder) RegisterKindEncoderFunc(kind reflect.Kind, encoder_func CustomEncoderFunc)
- func (encoder *Encoder) RegisterTypeEncoder(v interface{}, custom_encoder CustomEncoder)
- func (encoder *Encoder) RegisterTypeEncoderFunc(v interface{}, encoder_func CustomEncoderFunc)
- func (encoder *Encoder) SetWrappers(wrappers ...CustomEncoder)
- type EncoderChain
- type EncoderChainError
- type EncoderContext
- type EncoderWrapper
- type FieldsetWrapper
- type LabelWrapper
- type Range
- type SetMode
- type StructEncoder
- type StructNamingScheme
- type UnknownError
Examples ¶
Constants ¶
const ( // Plain `int` and `uint` types are different sizes on 32 and 64 bit systems // The following calculates the min / max ranges. // https://stackoverflow.com/questions/6878590/the-maximum-value-for-an-int-type-in-go MAX_UINT = ^uint(0) MAX_INT = int(MAX_UINT >> 1) MIN_INT = -MAX_INT - 1 MIN_INT64 = "-9223372036854775808" MAX_INT64 = "9223372036854775807" MIN_INT32 = "-2147483648" MAX_INT32 = "2147483647" MIN_INT16 = "-32768" MAX_INT16 = "32767" MIN_INT8 = "-128" MAX_INT8 = "127" MAX_UINT64 = "18446744073709551615" MAX_UINT32 = "4294967295" MAX_UINT16 = "65535" MAX_UINT8 = "255" )
const DATETIME_FORMAT = "2006-01-02T15:04:05"
Variables ¶
var ( RangeLookup = map[reflect.Kind]Range{ reflect.Int: { Min: fmt.Sprintf("%d", MIN_INT), Max: fmt.Sprintf("%d", MAX_INT), }, reflect.Int64: { Min: MIN_INT64, Max: MAX_INT64, }, reflect.Int32: { Min: MIN_INT32, Max: MAX_INT32, }, reflect.Int16: { Min: MIN_INT16, Max: MAX_INT16, }, reflect.Uint: { Min: "0", Max: fmt.Sprintf("%d", MAX_UINT), }, reflect.Int8: { Min: MIN_INT8, Max: MAX_INT8, }, reflect.Uint64: { Min: "0", Max: MAX_UINT64, }, reflect.Uint32: { Min: "0", Max: MAX_UINT32, }, reflect.Uint16: { Min: "0", Max: MAX_UINT16, }, reflect.Uint8: { Min: "0", Max: MAX_UINT8, }, } )
Functions ¶
func DefaultArrayNamer ¶
func DefaultStructNamer ¶
func EncodeBool ¶
func EncodeDateTime ¶
EncodeDateTime encodes a time.Time value. This reads the "type" attribute from any StructTag information and switches time format based on requested type.
Example ¶
type MyForm struct { Date time.Time `form:"type=date"` Time time.Time `form:"type=time"` DateTime time.Time } encoder := form.NewEncoder() parent := html.Node{ Type: html.ElementNode, Data: atom.Form.String(), DataAtom: atom.Form, } err := encoder.EncodeValue(&parent, MyForm{ Date: time.Date(2023, 9, 4, 0, 0, 0, 0, time.UTC), Time: time.Date(2023, 9, 4, 0, 0, 0, 0, time.UTC), DateTime: time.Date(2023, 9, 4, 0, 0, 0, 0, time.UTC), }) if err != nil { fmt.Println(err) return } PrettyRender(os.Stdout, &parent)
Output: <form> <input name="Date" type="date" value="2023-09-04"/> <input name="Time" type="time" value="00:00:00"/> <input name="DateTime" type="datetime-local" value="2023-09-04T00:00:00"/> </form>
func EncodeFloat64 ¶
func EncodeString ¶
func EncodeUint ¶
func NodeDeleteAttr ¶
Types ¶
type ArrayEncoder ¶
type ArrayEncoder struct {
NamingScheme ArrayNamingScheme
}
Example ¶
data := []string{ "Name 1", "Name 2", "Name 3", } encoder := form.NewEncoder() parent := html.Node{ Type: html.ElementNode, Data: atom.Form.String(), DataAtom: atom.Form, } encoder.EncodeValue(&parent, data) PrettyRender(os.Stdout, &parent)
Output: <form> <input name="0" type="text" value="Name 1"/> <input name="1" type="text" value="Name 2"/> <input name="2" type="text" value="Name 3"/> </form>
func NewArrayEncoder ¶
func NewArrayEncoder(namer ArrayNamingScheme) ArrayEncoder
func (*ArrayEncoder) Encode ¶
func (arrayEncoder *ArrayEncoder) Encode(context *EncoderContext, typeOf reflect.Type, valueOf reflect.Value) error
type ArrayNamingScheme ¶
type AttributeWrapper ¶
type AttributeWrapper struct {
FieldTag string
}
AttributeWrapper is a wrapper which extracts extra html attributes from a given struct tag. This is useful for overwriting certain html attributes via struct tags.
func NewAttributeWrapper ¶
func NewAttributeWrapper() AttributeWrapper
func (*AttributeWrapper) Encode ¶
func (wrapper *AttributeWrapper) Encode(context *EncoderContext, typeOf reflect.Type, valueOf reflect.Value) error
type CustomEncoder ¶
CustomEncoder is an interface for anything that can encode a reflected type and value.
type CustomEncoderFunc ¶
func (CustomEncoderFunc) Encode ¶
func (encoderFunc CustomEncoderFunc) Encode(context *EncoderContext, typeOf reflect.Type, valueOf reflect.Value) error
type Encoder ¶
func NewEmptyEncoder ¶
func NewEmptyEncoder() Encoder
NewEmptyEncoder creates an empty encoder with no registered encoders. Useful for building a completely custom set of encoders.
For more information on custom encoders see: Encoder.RegisterTypeEncoder Encoder.RegisterKindEncoder
func NewEncoder ¶
func NewEncoder() Encoder
NewEncoder creates an encoder with the default registered encoders.
Example ¶
type MyForm struct { A string A1 *string B int B1 *int C float64 C1 *float64 D time.Time D1 *time.Time E uint E1 *uint F bool F1 *bool } encoder := form.NewEncoder() parent := html.Node{ Type: html.ElementNode, Data: atom.Form.String(), DataAtom: atom.Form, } a1 := "some string" b1 := 2121 c1 := 3333.0 d1 := time.Date(2024, 8, 28, 0, 0, 0, 0, time.UTC) e1 := uint(302910) f1 := true err := encoder.EncodeValue(&parent, MyForm{ A: "A string", A1: &a1, B: 2, B1: &b1, C: 3.0, C1: &c1, D: time.Date(2023, 8, 28, 0, 0, 0, 0, time.UTC), D1: &d1, E: uint(109812309), E1: &e1, F: false, F1: &f1, }) if err != nil { fmt.Println(err) return } PrettyRender(os.Stdout, &parent)
Output: <form> <input name="A" type="text" value="A string"/> <input name="A1" type="text" value="some string"/> <input name="B" type="number" value="2" min="-9223372036854775808" max="9223372036854775807"/> <input name="B1" type="number" value="2121" min="-9223372036854775808" max="9223372036854775807"/> <input name="C" type="number" step="any" value="3.000000"/> <input name="C1" type="number" step="any" value="3333.000000"/> <input name="D" type="datetime-local" value="2023-08-28T00:00:00"/> <input name="D1" type="datetime-local" value="2024-08-28T00:00:00"/> <input name="E" type="number" value="109812309" min="0" max="18446744073709551615"/> <input name="E1" type="number" value="302910" min="0" max="18446744073709551615"/> <input name="F" type="checkbox"/> <input name="F1" type="checkbox" checked="true"/> </form>
Example (Basic_example) ¶
package main import ( "fmt" "os" "gitlab.com/sj1k/form" "golang.org/x/net/html" "golang.org/x/net/html/atom" ) func main() { type Signup struct { Name string `label:"Some label here!"` Pass string `label:"Enter a password!" attr:"type=password"` Age int } // AttrbuteWrapper extracts and applies attributes from struct tags. // This will load attributes from the `attr` tag. attrWrapper := form.NewAttributeWrapper() // LabelWrapper wraps the input with a <label> element if the `label:""` tag exists. labelWrapper := form.NewLabelWrapper() encoder := form.NewEncoder() encoder.SetWrappers(&labelWrapper, &attrWrapper) parent := CreateFormNode() err := encoder.EncodeValue(&parent, &Signup{}) if err != nil { fmt.Println(err) return } PrettyRender(os.Stdout, &parent) } func CreateFormNode() html.Node { return html.Node{ Type: html.ElementNode, Data: atom.Form.String(), DataAtom: atom.Form, } }
Output: <form> <label>Some label here! <input name="Name" type="text"/> </label> <label>Enter a password! <input type="password" name="Pass"/> </label> <input name="Age" type="number" value="0" min="-9223372036854775808" max="9223372036854775807"/> </form>
func (*Encoder) AppendWrappers ¶
func (encoder *Encoder) AppendWrappers(wrappers ...CustomEncoder)
AppendWrappers appends more wrappers to be run before each encoder.
func (*Encoder) EncodeValue ¶
EncodeValue starts encoding the given value and appends results to the given parent. This is the main entry point for form generation.
func (*Encoder) RegisterKindEncoder ¶
func (encoder *Encoder) RegisterKindEncoder(kind reflect.Kind, custom_encoder CustomEncoder)
RegisterKindEncoder uses the reflect.Kind of the given value to register a CustomEncoder To use a function for encoding see Encoder.RegisterKindEncoderFunc
func (*Encoder) RegisterKindEncoderFunc ¶
func (encoder *Encoder) RegisterKindEncoderFunc(kind reflect.Kind, encoder_func CustomEncoderFunc)
func (*Encoder) RegisterTypeEncoder ¶
func (encoder *Encoder) RegisterTypeEncoder(v interface{}, custom_encoder CustomEncoder)
RegisterTypeEncoder uses the reflect.Type of the given value to register a CustomEncoder To use a function for encoding see [ENcoder.RegisterTypeEncoderFunc]
Example ¶
encoder := form.NewEmptyEncoder() encoder.RegisterTypeEncoder("string", &ParagraphEncoder{}) parent := html.Node{ Type: html.ElementNode, Data: atom.P.String(), DataAtom: atom.P, } err := encoder.EncodeValue(&parent, "Some Value") if err != nil { fmt.Println(err) return } PrettyRender(os.Stdout, &parent)
Output: <p>Some Value</p>
func (*Encoder) RegisterTypeEncoderFunc ¶
func (encoder *Encoder) RegisterTypeEncoderFunc(v interface{}, encoder_func CustomEncoderFunc)
func (*Encoder) SetWrappers ¶
func (encoder *Encoder) SetWrappers(wrappers ...CustomEncoder)
SetWrappers sets / overwrites which wrappers will be run before each encoder.
type EncoderChain ¶
type EncoderChain struct {
Encoders []CustomEncoder
}
EncoderChain calls a chain of other CustomEncoder's. The encoders are called in regular iteration order.
func ChainEncoders ¶
func ChainEncoders(encoders ...CustomEncoder) EncoderChain
func (EncoderChain) Encode ¶
func (chain EncoderChain) Encode(context *EncoderContext, typeOf reflect.Type, valueOf reflect.Value) error
type EncoderChainError ¶
func (EncoderChainError) Error ¶
func (chainError EncoderChainError) Error() string
type EncoderContext ¶
type EncoderWrapper ¶
type EncoderWrapper struct { Wrapper CustomEncoder Encoder CustomEncoder }
func WrapEncoder ¶
func WrapEncoder(wrapper CustomEncoder, encoder CustomEncoder) EncoderWrapper
WrapEncoder creates a new EncoderWrapper with a given wrapper and encoder. If you need multiple wrappers it may be worth using an EncoderChain
func (EncoderWrapper) Encode ¶
func (wrapper EncoderWrapper) Encode(context *EncoderContext, typeOf reflect.Type, valueOf reflect.Value) error
type FieldsetWrapper ¶
type FieldsetWrapper struct {
FieldTag string
}
FieldsetWrapper is a wrapper which creates <fieldset> wrappers around nodes when a given struct tag is found. Optionally creates a <legend> if the struct tag has content.
Example ¶
type MyForm struct { With string `fieldset:"With a label"` Without string `fieldset:""` } fieldset := form.NewFieldsetWrapper() // attributes := form.NewAttributeWrapper() encoder := form.NewEncoder() encoder.SetWrappers( // &attributes, &fieldset, ) parent := html.Node{ Type: html.ElementNode, Data: atom.Form.String(), DataAtom: atom.Form, } err := encoder.EncodeValue(&parent, MyForm{ With: "with label", Without: "without label", }) if err != nil { fmt.Println(err) return } PrettyRender(os.Stdout, &parent)
Output: <form> <fieldset> <legend>With a label</legend> <input name="With" type="text" value="with label"/> </fieldset> <fieldset> <input name="Without" type="text" value="without label"/> </fieldset> </form>
func NewFieldsetWrapper ¶
func NewFieldsetWrapper() FieldsetWrapper
func (*FieldsetWrapper) Encode ¶
func (wrapper *FieldsetWrapper) Encode(context *EncoderContext, typeOf reflect.Type, valueOf reflect.Value) error
type LabelWrapper ¶
type LabelWrapper struct {
FieldTag string
}
func NewLabelWrapper ¶
func NewLabelWrapper() LabelWrapper
func (*LabelWrapper) Encode ¶
func (wrapper *LabelWrapper) Encode(context *EncoderContext, typeOf reflect.Type, valueOf reflect.Value) error
type SetMode ¶
type SetMode int
SetMode is used to know if NodeSetAttr should overwrite attributes or not. See NodeSetAttr
type StructEncoder ¶
type StructEncoder struct {
NamingScheme StructNamingScheme
}
func NewStructEncoder ¶
func NewStructEncoder(namer StructNamingScheme) StructEncoder
func (*StructEncoder) Encode ¶
func (structEncoder *StructEncoder) Encode(context *EncoderContext, typeOf reflect.Type, valueOf reflect.Value) error
type StructNamingScheme ¶
type UnknownError ¶
func (UnknownError) Error ¶
func (err UnknownError) Error() string
Source Files ¶
- array_encoder.go
- attribute_wrapper.go
- bool_encoder.go
- chain.go
- context.go
- custom_encoder.go
- datetime_encoder.go
- doc.go
- encoder.go
- encoder_chain_error.go
- fieldset_wrapper.go
- float_encoder.go
- int_encoder.go
- label_wrapper.go
- node.go
- parse_tag.go
- string_encoder.go
- struct_encoder.go
- uint_encoder.go
- unknown_error.go
- valid_range.go
- wrapper.go
Directories ¶
Path | Synopsis |
---|---|
label_parser
module
|
|
schema_parser
module
|
|
tag_parsers
module
|
|
schema
Module
|