lomake

package module
v0.0.0-...-e3e2d7a Latest Latest
Warning

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

Go to latest
Published: Jul 6, 2018 License: Apache-2.0 Imports: 7 Imported by: 0

README

lomake

HTML Form generator from Go structs

With lomake HTML form for registration:

<form id="pageform" action="/api/account/register.json" method="post">
    <!-- User -->
    <div class="form-group required"><label for="Username">* User name</label>
        <input class="form-control" type="text"
               name="Username" id="Username"
               value=""
               placeholder="Enter your user name"/>
    </div>
    
    <!-- Email -->
    <div class="form-group required"><label for="EmailAddress">* E-mail address</label>
        <input class="form-control"
               type="text"
               name="EmailAddress"
               id="EmailAddress" value=""
               placeholder="Enter your e-mail"/>
    </div>

    <!-- Password -->
    <div class="form-group required"><label for="Password">* Password</label>
        <input class="form-control" type="password"
               name="Password" id="Password"
               value=""
               placeholder="%mYs3cr37p455w0rd"/>
    </div>
    <!-- Password (again) -->
    <div class="form-group required"><label for="Password2">* Password (again)</label>
        <input class="form-control"
               type="password"
               name="Password2"
               id="Password2" value=""
               placeholder="%mYs3cr37p455w0rd"/>
    </div>

    <!-- Submit -->
    <input id="formsubmit" type="submit" class="btn-primary" value="Send"/>
</form>

Becomes:

type RegisterForm struct {
	Username     string `json:"," lomaketype:"input.text"`
	EmailAddress string `json:"," lomaketype:"input.text"`
	Password     string `json:"," lomaketype:"input.password"`
	Password2    string `json:"," lomaketype:"input.password"`
}

It also supports internationalization (i18n) out of the box, so that all field placeholders etc can be translated.

package main

import (
	"html/template"
	"log"
	"fmt"
	"reflect"
	"bytes"
	"golang.org/x/text/message"
	"golang.org/x/text/language"
	"github.com/raspi/lomake"
)

type RegisterForm struct {
	Username     string `json:"," lomaketype:"input.text"`
	EmailAddress string `json:"," lomaketype:"input.text"`
	Password     string `json:"," lomaketype:"input.password"`
	Password2    string `json:"," lomaketype:"input.password"`
}

var pageTemplate = `
<form id="pageform" action="/api/account/register.json" method="post">
	{{- .Form -}}
    <input id="formsubmit" type="submit" class="btn-primary" value="{{ T "form.submit" }}" />
</form>
`

// Get HTML
func (f RegisterForm) HTML() template.HTML {
	// TODO cache
	out, err := lomake.New(&f)
	if err != nil {
		log.Fatalf(`error=%v`, err)
		return ``
	}

	return out
}

func main() {

	// -- Global:
	translator := message.NewPrinter(language.Finnish)

	t := template.New("")

	t = t.Funcs(template.FuncMap{
		"T": func(s string, a ...interface{}) string {
			ref := message.Key(s, fmt.Sprintf(`NOT TRANSLATED: '%v'`, s))
			return translator.Sprintf(ref, a...)
		},
	})

	t.Parse(pageTemplate)

	lomake.Translator = translator
	lomake.HTMLTemplate = t

	// -- Page (view):
	var buf bytes.Buffer
	page, err := t.Clone()

	// Render form
	var form RegisterForm
	view := struct {
		Form template.HTML
	}{
		Form: form.HTML(),
	}

	page.Execute(&buf, &view)
	fmt.Println(buf.String())
}

// Ignore, used to get the package name
type Empty struct{}

// Initialize translations
func init() {
	pkgName := reflect.TypeOf(Empty{}).PkgPath()

	prefix := fmt.Sprintf(`lomake.%v`, pkgName)

	t := make(map[string]map[language.Tag]string)

	t[fmt.Sprintf(`%v.Username`, prefix)] = map[language.Tag]string{
		language.English: `User name`,
		language.Finnish: `Käyttäjätunnus`,
	}

	t[fmt.Sprintf(`%v.Username.placeholder`, prefix)] = map[language.Tag]string{
		language.English: `Enter your user name`,
		language.Finnish: `Syötä käyttäjätunnuksesi`,
	}


	t[fmt.Sprintf(`%v.EmailAddress`, prefix)] = map[language.Tag]string{
		language.English: `E-mail address`,
		language.Finnish: `Sähköpostiosoite`,
	}

	t[fmt.Sprintf(`%v.EmailAddress.placeholder`, prefix)] = map[language.Tag]string{
		language.English: `Enter your e-mail`,
		language.Finnish: `Syötä sähköpostiosoitteesi`,
	}

	t[fmt.Sprintf(`%v.Password`, prefix)] = map[language.Tag]string{
		language.English: `Password`,
		language.Finnish: `Salasana`,
	}

	t[fmt.Sprintf(`%v.Password2`, prefix)] = map[language.Tag]string{
		language.English: `Password (again)`,
		language.Finnish: `Salasana (uudestaan)`,
	}

	t[fmt.Sprintf(`%v.Password.placeholder`, prefix)] = map[language.Tag]string{
		language.English: `%%mYs3cr37p455w0rd`,
		language.Finnish: `sAl454N4%%`,
	}

	t[fmt.Sprintf(`%v.Password2.placeholder`, prefix)] = map[language.Tag]string{
		language.English: t[fmt.Sprintf(`%v.Password.placeholder`, prefix)][language.English],
		language.Finnish: t[fmt.Sprintf(`%v.Password.placeholder`, prefix)][language.Finnish],
	}

	t[`form.submit`] = map[language.Tag]string{
		language.English: `Send`,
		language.Finnish: `Lähetä`,
	}

	for key,_ := range t {
		for lang, v := range t[key] {
			message.SetString(lang, key, v )
		}
	}
}

Documentation

Index

Constants

View Source
const (
	LOMAKE_TYPE_FIELD = `lomaketype`
)

Variables

Order of how decorators are applied

View Source
var DecoratorMap = map[string]DecoratorType{
	"input.text":     INPUT_TEXT,
	"input.password": INPUT_PASSWORD,
	"input.hidden":   INPUT_HIDDEN,
	"textarea":       TEXTAREA,
}

map string into decorator

View Source
var DecoratorTemplates = map[DecoratorType]string{
	DIV:            `<div class="form-group{{ if .Item.Required }} required{{ end }}">{{- .Parent -}}</div>`,
	LABEL:          `<label for="{{- .Item.Name -}}">{{ if .Item.Required }}* {{ end }}{{- T .Item.Description -}}</label>{{- .Parent -}}`,
	TEXTAREA:       `{{- .Parent -}}<textarea class="form-control" name="{{- .Item.Name -}}" id="{{- .Item.Name -}}" placeholder="{{- T .Item.Placeholder -}}">{{- .Item.Value -}}</textarea>`,
	INPUT_PASSWORD: `{{- .Parent -}}<input class="form-control" type="password" name="{{- .Item.Name -}}" id="{{- .Item.Name -}}" value="{{- .Item.Value -}}" placeholder="{{- T .Item.Placeholder -}}" />`,
	INPUT_TEXT:     `{{- .Parent -}}<input class="form-control" type="text" name="{{- .Item.Name -}}" id="{{- .Item.Name -}}" value="{{- .Item.Value -}}" placeholder="{{- T .Item.Placeholder -}}" />`,
	INPUT_HIDDEN:   `{{- .Parent -}}<input type="hidden" name="{{- .Item.Name -}}" id="{{- .Item.Name -}}" value="{{- .Item.Value -}}" />`,
}

Base HTML templates .Parent is the parent decorator

View Source
var HTMLTemplate *template.Template

Template for generating HTML

View Source
var Translator *message.Printer

Translate form labels, placeholders, ..

Functions

func New

func New(iface interface{}) (h template.HTML, err error)

Convert struct into HTML form

func NewStructureDescription

func NewStructureDescription() structureDescription

Types

type DecoratorType

type DecoratorType uint64
const (
	DIV DecoratorType = iota
	LABEL
	TEXTAREA
	INPUT_PASSWORD
	INPUT_TEXT
	INPUT_HIDDEN
)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL