Categorygithub.com/cj123/formulate
modulepackage
1.6.0
Repository: https://github.com/cj123/formulate.git
Documentation: pkg.go.dev

# README

formulate Godoc

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

# Packages

No description provided by the author
No description provided by the author

# 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.