Version: v0.0.0-...-2562bae Latest Latest

This package is not in the latest version of its module.

Go to latest
Published: Apr 7, 2017 License: MIT Imports: 10 Imported by: 0



Package form provides utilities for creating and accessing HTML forms.

This is an abstraction for defining forms in text, and accessing them accordingly. It is partially inspired by Drupal's form library.

This generates HTML5 forms.

In this package, you will find:

- a Form type for declaring a new form
- types for each form field type
- the FormHandler for automating form storage, submission, and retrieval
- secure tokens for mitigating XSS attacks
- a caching framework for storing form data (used by FormHandler)

Engine also provides templates for rendering a form into HTML. The expected form workflow goes something like this:

1. Declare a form in-code
2. Prepare the form, which adds security and caches a copy
3. Render the form to HTML and serve it to the client
4. On form submission, get the form values
5. Look up the form and populate it with the submitted values
6. Work with the returned form

The example below illustrates how most of this is done by the library.

// Create a new form:
f := New("My Form", "/submit")

// Add some fields
f.Fields = []Field{
	&Text{Name: "username"},
	&Password{Name: "password"},

// Prepare the form using the default form handler.
id, err := DefaultFormHandler.Prepare(f)
if err != nil {
	fmt.Printf("Error preparing form: %s", err)

// Render the form to the user agent. Typlically you do this
// with a template.

// When the form is submitted, it will return something like this:
vals := &url.Values{
	"username":      []string{"matt"},
	"password":      []string{"secret"},
	SecureTokenName: []string{id},

// We can pass in the values and retrieve the form, with the values
// all entered on the appropriate element.
ff, err := DefaultFormHandler.Retrieve(vals)
if err != nil {
	fmt.Printf("Failed to retrieve form: %s", err)

// Now we can access the fields directly
user := ff.Fields[0].(*Text).Value
pass := ff.Fields[1].(*Password).Value






View Source
const (
	// Left-to-right
	LTR = "ltr"
	// Right-to-left
	RTL = "rtl"
	// Determine based on UA
	Auto = "auto"


View Source
var DefaultFormHandler = NewFormHandler(NewCache(), time.Hour*24)

DefaultFormHandler is a form handler initialized with an in-memory cache and a 24 hour expiration on form data.

View Source
var ErrFormNotFound = errors.New("Form not found")

FormNotFound indicates that a form is not in the cache.

Expired records should also return this error.

View Source
var ErrNoToken = errors.New("No token provided")

ErrNoToken indicates that provided form data has no security token.

View Source
var SecureTokenName = "__token__"

The name of the token that is automatically placed into a form.

This should never be modified after a form has been generated.

View Source
var SecurityTokenLength = 32

The length of the security token.

View Source
var SweepInterval = 5 * time.Minute

SweepInterval is a suggested interval for sweeping the cache.

It is not mandatory that caching backends use SweepInterval, but the default caching mechanism uses it to indicate how frequently it should purge the cache of expired records.


func Reconcile

func Reconcile(fm *Form, data *url.Values) error

Reconcile modifies a form in place, merging the data into the form's Value fields.

Validation is not handled by the reconciler.

Normally, reconciliation will happen via the FormHandler's Retrieve method.

func SecurityToken

func SecurityToken() string

Generate a security token.

This uses SecurityTokenLength to determine the appropriate length. If that value is <= 0, this will panic.


type Button

type Button struct {
	Autofocus, Disabled           bool
	Form, Menu, Name, Type, Value string

func NewButton

func NewButton(name, val string) *Button

type ButtonInput

type ButtonInput Input

Button provides a generic button. This is deprecated in favor of the Button type.

type Cache

type Cache interface {
	Get(id string) (*Form, error)
	Set(id string, f *Form, expires time.Time) error
	Remove(id string) error

Cache provides storage for forms.

Generally, a cache is not used directly. Instead, the FormHandler is used.

Cache implementations are required to handle expiration internally.

func NewCache

func NewCache() Cache

NewCache returns a new Cache backed by an in-memory cache.

TODO: An in-memory cache is currently designed to last the lifetime of an application. There is no way to stop and cleanup the cache.

type CacheVal

type CacheVal struct {
	// contains filtered or unexported fields

CacheVal describes a value in the cache.

Timeout indicates when the current form is no longer valid, and can be cleaned up.

type Checkbox

type Checkbox Input

Checkbox provides a single checkbox.

type Color

type Color Input

Color provides a color picker.

type DataList

type DataList struct {
	Options []*Option

DataList is a hidden option list used by other fields.

type Date

type Date Input

Date provides a date form entry field.

type Div

type Div struct {
	Fields []Field

Divs are generic containers for fields.

Because divs are frequently used to segment forms, we support them explicitly.

type Email

type Email Input

Email provides an Email address field.

type Field

type Field interface{}

Field describes any form element.

type FieldSet

type FieldSet struct {
	Form, Name string
	Disabled   bool
	Fields     []Field

	// This is not an attribute, but we should auto-generate the results.
	Legend string

FieldSet describes a set of form fields.

type File

type File Input

File provides a file upload field.

type Form

type Form struct {
	AcceptCharset, Enctype, Action, Method, Name, Target string
	Autocomplete, Novalidate                             bool
	Fields                                               []Field

Form describes an HTML5 form.

A form can encapsulate an arbitrary number of form.Field objects.

Forms can be create with the New() function, or instantiated directly. Then are typically rendered through the form templating system.

func New

func New(name, action string) *Form

New creates a new form with the Name and Action fields set.

func (*Form) Add

func (f *Form) Add(field ...Field) *Form

Add adds any number of fields to a form.

func (*Form) AsValues

func (f *Form) AsValues() *url.Values

AsValues converts a form to its name/value pairs.

This is a "lossy" conversion. It only retains elements that have a meaningful notion of "value" (like text, select, button, and checkbox), but omits elements like Div, Output, OptGroup, and FieldSet that do not have a meaningful notion of value.

For fields that commonly can have multiple values (Select, Checkbox), values are appended. For elements that do not admit multiple values (Text, Radio, TextArea, etc), only one value is set.

func (*Form) Element

func (f *Form) Element() *html.Node

Element retrieves the form as an html.Node of type ElementNode.

type FormElement

type FormElement interface {
	Element() *html.Node

FormElement describes any form element capable of expression as an html.Node.

type FormHandler

type FormHandler struct {

	// The duration a form will be kept before it expires.
	Expiration time.Duration
	// contains filtered or unexported fields

FormHandler manages the cache-and-load lifecycle of forms.

FormHandler enforces security constraints on forms, and will modify forms in place.

func NewFormHandler

func NewFormHandler(c Cache, expiration time.Duration) *FormHandler

NewFormHandler creates a new FormHandler.

func (*FormHandler) Get

func (f *FormHandler) Get(id string) (*Form, error)

func (*FormHandler) Prepare

func (f *FormHandler) Prepare(form *Form) (string, error)

Prepare modifies the form for caching and security, then inserts it into cache.

This will add a security field to the end of the form's Fields list. The generated ID will be returned. And the form will be placed into the cache.

This form can later be retrieved using the returned ID.

func (*FormHandler) Remove

func (f *FormHandler) Remove(id string) error

func (*FormHandler) Retrieve

func (f *FormHandler) Retrieve(data *url.Values) (*Form, error)

Retrieve uses a request's key/value pairs to populate a cached form.

It then decodes the submission data into the relevant cached form, and returns the form. The Value fields on each form element will be set according to the data. If the form data was not set for a particular field, that field will be left alone (which means that if it had a default value, that will remain in effect).

Finally, Retrieve will remove the form from the cache, since a form cannot be re-used.

The implementing function must pass in the appropriate set of values. The "net/http" library makes Get, Post, Put, and Patch variables all available as *url.Values.

type HTML

type HTML struct {
	Class                                                       []string
	AccessKey, Id, Dir, Lang, Style, TabIndex, Title, Translate string
	ContentEditable, Hidden                                     OptionalBool
	Role                                                        string

	// Data stores arbitrary attributes, such as data-* fields. It is up to
	// the implementation to know how to deal with these fields.
	Data map[string]string

	// Attributes prefixed "aria-"
	Aria map[string]string

HTML captures a group of attributes common across all HTML elements.

These attributes are all defined as Global, ARIA and Data attributes in the HTML5 specification. Because all of these can be applied to any form content, they are exposed here.

The allowed values for all of these are explained in the HTML5 spec. Because we strive more for expression in the browser than semantic correctness, here and elsewhere we rarely force a particular value to conform to the spec. Typically, typing is as close as we get to enforcement.

func (HTML) Attach

func (g HTML) Attach(node *html.Node)

Attache attaches these attributes to an html.Node.

func (HTML) EnsureId

func (g HTML) EnsureId(seed string) string

EnsureId ensures that an HTML has an ID attribute.

type Hidden

type Hidden Input

Hidden provides a field that will not be displayed.

func SecurityField

func SecurityField() Hidden

SecurityField returns a Hidden form element initialized with a security token.

type Image

type Image Input

Image provides a button that is painted with an image.

type Input

type Input struct {
	Accept, Alt, Autocomplete, Dirname, Form, List, InputMode, Max, Min, MaxLength string
	Name, Pattern, Placeholder, Src, Step, Value                                   string
	Autofocus, Checked, Disabled, Multiple, ReadOnly, Required                     bool
	Height, Width, Size                                                            uint64

	// Technically, this is not an attribute of an Input field, but we put it here
	// to simplify the process of labeling fields.
	Label string

Input defines a generic untyped form field.

It should not generally be used directly.

type Keygen

type Keygen struct {
	Challenge, Form, KeyType, Name string
	Autofocus, Disabled            bool
	Value                          string

Keygen describes the keygen form field type.

type Label

type Label struct {
	For, Form string
	//Content   html.Node
	Text string

Label describes a label for a field.

Because labels are almost always applied to specific fields, and because the rules for attaching a label to a field vary by field type, more often than not you should favor a field's Label property over adding a Label element directly.

func NewLabel

func NewLabel(forName, text string) *Label

NewLabel creates a new label.

type Meter

type Meter struct {
	Value, Min, Max, Low, High, Optimum float64

Meter defines a generic meter form element type.

type Number

type Number Input

Number provides a numeric field.

type OptGroup

type OptGroup struct {
	Label    string
	Disabled bool
	Options  []*Option

OptGroup describes a list of options.

type Option

type Option struct {
	Disabled, Selected bool
	// A label is the user-visible text, while the value is what is
	// sent to the server. Label may be rendered as phrasing content.
	Label, Value string

Option describes an individual option in a selection, datalist, or optgroup.

type OptionItem

type OptionItem interface{}

OptionItem describes any item that can be a member of an options list.

Select fields allow option items, while DataLists are more strict, and require Option types.

type OptionalBool

type OptionalBool uint8
const (
	// Nothing set, results in inheriting parent settings.
	ONone OptionalBool = iota
	// True
	// False

type Output

type Output struct {
	For, Form, Name string

Output describes an output form field.

type Password

type Password Input

Password provides a field for obscured text.

type Progress

type Progress struct {
	Value, Max float64

Progress defines a progress meter form element type.

type Radio

type Radio Input

Radio provides a single radio button.

type Range

type Range Input

Range provides a number range field.

type Reset

type Reset Input

Reset provides a button that is pre-wired to reset the form.

type Select

type Select struct {
	Autofocus, Disabled, Multiple, Required bool
	Form, Name                              string
	Size                                    uint64
	Options                                 []OptionItem
	Label                                   string

Select defines a selection list form element.

type String

type String string

String is for PCData that can be arbitarily embeded in a []Field list.

type Submit

type Submit Input

Submit provides a button pre-wired for submission.

type Tel

type Tel Input

Tel provides a telephone number field.

type Text

type Text Input

Text provides a single text entry line. See TextArea for multi-line input.

type TextArea

type TextArea struct {
	Autocomplete, Dirname, Form, Name, Placeholder, Wrap string
	Autofocus, Disabled, ReadOnly, Required              bool
	Cols, MaxLength, MinLength, Rows                     uint64
	Value                                                string

TextArea describes a multi-line multi-column text entry form field.

type Time

type Time Input

Time provides a time form entry field.

type URL

type URL Input

URL provides a URL field.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
t or T : Toggle theme light dark auto
y or Y : Canonical URL