# README
formulate 
a HTML form builder and HTTP request to struct parser.
Example (Formulate)
type Address struct {
HouseName string `help:"You can leave this blank."`
AddressLine1 string
AddressLine2 string
Postcode string
TelephoneNumber Tel
CountryCode string `pattern:"[A-Za-z]{3}" validators:"countryCode"`
}
buildEncoder := func(r *http.Request, w io.Writer) *HTMLEncoder {
enc := NewEncoder(w, r, nil)
enc.SetFormat(true)
return enc
}
buildDecoder := func(r *http.Request, values url.Values) *HTTPDecoder {
dec := NewDecoder(values)
dec.SetValueOnValidationError(true)
dec.AddValidators(countryCodeValidator{})
return dec
}
handler := func(w http.ResponseWriter, r *http.Request) {
var addressForm Address
encodedForm, save, err := Formulate(r, &addressForm, buildEncoder, buildDecoder)
if err == nil && save {
// save the form here
http.Redirect(w, r, "/", http.StatusFound)
} else if err != nil {
http.Error(w, "Bad Form", http.StatusInternalServerError)
return
}
w.Header().Add("Content-Type", "text/html")
_, _ = w.Write(encodedForm)
}
// example validator
type countryCodeValidator struct{}
func (c countryCodeValidator) Validate(value interface{}) (ok bool, message string) {
switch a := value.(type) {
case string:
if len(a) == 3 && strings.ToUpper(a) == a {
return true, ""
}
return false, "Country codes must be 3 letters and uppercase"
default:
return false, "invalid type"
}
}
func (c countryCodeValidator) TagName() string {
return "countryCode"
}
Example (Encoder)
type Address struct {
HouseName string `help:"You can leave this blank."`
AddressLine1 string
AddressLine2 string
Postcode string
TelephoneNumber Tel
CountryCode string `pattern:"[A-Za-z]{3}"`
}
buf := new(bytes.Buffer)
address := Address{
AddressLine1: "Fake Street",
}
encoder := NewEncoder(buf, nil, nil)
encoder.SetFormat(true)
if err := encoder.Encode(&address); err != nil {
panic(err)
}
fmt.Println(buf.String())
Output:
<div>
<fieldset>
<div>
<label for="HouseName">
House Name
</label>
<div>
<input type="text" name="HouseName" id="HouseName" value=""/>
<div>You can leave this blank.</div>
</div>
</div>
<div>
<label for="AddressLine1">
Address Line 1
</label>
<div>
<input type="text" name="AddressLine1" id="AddressLine1" value="Fake Street"/>
<div></div>
</div>
</div>
<div>
<label for="AddressLine2">
Address Line 2
</label>
<div>
<input type="text" name="AddressLine2" id="AddressLine2" value=""/>
<div></div>
</div>
</div>
<div>
<label for="Postcode">
Postcode
</label>
<div>
<input type="text" name="Postcode" id="Postcode" value=""/>
<div></div>
</div>
</div>
<div>
<label for="TelephoneNumber">
Telephone Number
</label>
<div>
<input type="tel" name="TelephoneNumber" id="TelephoneNumber" value=""/>
<div></div>
</div>
</div>
<div>
<label for="CountryCode">
Country Code
</label>
<div>
<input type="text" name="CountryCode" id="CountryCode" value="" pattern="[A-Za-z]{3}"/>
<div></div>
</div>
</div>
</fieldset>
</div>
Example (Decoder)
type Address struct {
HouseName string `help:"You can leave this blank."`
AddressLine1 string
AddressLine2 string
Postcode string
TelephoneNumber Tel
CountryCode string `pattern:"[A-Za-z]{3}"`
}
// formValues - usually these would come from *http.Request.Form!
formValues := url.Values{
"HouseName": {"1 Example Road"},
"AddressLine1": {"Fake Town"},
"AddressLine2": {"Fake City"},
"Postcode": {"Postcode"},
"TelephoneNumber": {"012345678910"},
"CountryCode": {"GBR"},
}
var address Address
decoder := NewDecoder(formValues)
if err := decoder.Decode(&address); err != nil {
panic(err)
}
fmt.Printf("House Name: %s\n", address.HouseName)
fmt.Printf("Line 1: %s\n", address.AddressLine1)
fmt.Printf("Line 2: %s\n", address.AddressLine2)
fmt.Printf("Postcode: %s\n", address.Postcode)
fmt.Printf("Telephone: %s\n", address.TelephoneNumber)
fmt.Printf("CountryCode: %s\n", address.CountryCode)
Output:
House Name: 1 Example Road
Line 1: Fake Town
Line 2: Fake City
Postcode: Postcode
Telephone: 012345678910
CountryCode: GBR
# Functions
AppendClass adds a class to a HTML node.
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
FormElementName returns the name of the form element within the form, removing the package path and base struct name.
Formulate is an all-in-one method for handling form encoding and decoding, including validation errors.
HasAttribute returns true if n has the attribute named attr.
NewCondition creates a new condition based on a bool value.
NewDecoder creates a new HTTPDecoder.
NewEncoder returns a HTMLEncoder which outputs to w.
No description provided by the author
No description provided by the author
PopFormValue takes a value from the form and removes it so that it is not parsed again.
RenderHTMLToNode renders a html string into a parent *html.Node.
# Variables
ErrFormFailedValidation is returned if any form fields did not pass validation.
ErrInvalidCSRFToken indicates that the csrf middleware has not been loaded in the handler chain.
# Structs
HTMLEncoder is used to generate an HTML form from a given struct.
HTTPDecoder takes a set of url values and decodes them.
No description provided by the author
Option represents an option in Select inputs and Radio inputs.
StructField is a wrapper around the reflect.StructField type.
ValidationError is an error generated by the validation process.
# Interfaces
CustomDecoder allows for custom decoding behavior to be specified for an element.
CustomEncoder allows for custom rendering behavior of a type to be implemented.
Decorator is used to customise node elements that are built by the HTMLEncoder.
FormAwareValidator is a Validator that is aware of the full form that was posted.
RadioList represents a list of <input type="radio">.
Select represents a HTML <select> element.
ValidationStore is a data store for the validation errors.
Validator is an interface that allows individual form fields to be validated as part of the Decode phase of a formulate form.
# Type aliases
BoolNumber represents an int (0 or 1) which should actually be rendered as a checkbox.
Condition are optional booleans for Options.
No description provided by the author
HTMLEncoderBuilder is a function that builds a HTMLEncoder given an io.Writer as the output.
HTTPDecoderBuilder is a function that builds a HTTPDecoder given the form as the input.
No description provided by the author
Raw is byte data which should be rendered as a string inside a textarea.
ShowConditionFunc is a function which determines whether to show a form element.
No description provided by the author
No description provided by the author
No description provided by the author
ValidatorKey is used to match the Validator's TagName against that on a StructField.