This package contains all input implementations for webtyp/form.
Each input implements model.Kind (Type, Validate, Clone) plus metadata getters.
Inputs are render-free: they carry no dom/html imports. Rendering is done by the
form package via RenderInput(input.Input). All inputs use only webtyp/fmt —
no errors or strconv from the standard library.
| Type | HTML type | Validation rules |
|---|---|---|
Address |
text |
Letters, Numbers, . , - # /, Min: 5, Max: 200 |
Checkbox |
checkbox |
true, false, on, 1, 0 or empty |
Date |
date |
YYYY-MM-DD format, leap year + month/day range check |
Datalist |
text |
Value must match one of the registered Options.Key |
Decimal |
number |
Digits, ., -, Min: 1, Max: 20 chars — storage FieldFloat (see note) |
Email |
email |
Letters, Numbers, @ . _ -, Min: 5, Max: 100 |
Filepath |
text |
Letters, digits, .\/- _, no whitespace, Min: 1 |
Gender |
radio |
m/f pre-wired options |
Hour |
time |
HH:MM format, digits + :, validates 24h range |
IP |
text |
IPv4 or IPv6 format; 0.0.0.0 rejected |
MAC |
text |
12 hex digits, plain or :/- separated; see CanonicalMAC, IsLocallyAdministeredMAC |
Number |
number |
Digits only (0-9), Min: 1, Max: 20 chars |
Password |
password |
Any char, Min: 5, Max: 50 |
Phone |
tel |
Digits, + ( ) -, Min: 7, Max: 15 |
Radio |
radio |
Value must match one of the registered Options.Key |
Rut |
text |
Chilean RUT XXXXXXX-D, verifies check digit |
Search |
search |
Letters, Numbers, Spaces, Min: 0, Max: 100 — optional |
Select |
select |
Value must match one of the registered Options.Key |
Text |
text |
Letters, Numbers, . , ( ), Min: 2, Max: 100 |
Textarea |
textarea |
Wide char set incl. \n, Min: 5, Max: 2000 |
Number vs Decimal: both render the same <input type="number">. The difference is
Storage() — Number() reports model.FieldInt (int64), Decimal() reports model.FieldFloat
(float64). Use Decimal for any field with fractional precision (price, measurements,
percentages, ...); using Number there silently truncates the value to a whole number.
Rule: All input files must import only
webtyp.com/fmt. Noerrors,strconv, orstrings.
Use the webtyp/fmt equivalents:
// Instead of strconv.Atoi:
val, err := fmt.Convert("42").Int()
// Instead of errors.New:
return fmt.Err("Field", "Invalid")
// Instead of strings.ToLower:
lower := fmt.Convert(s).ToLower().String()
// Instead of strings.Contains:
found := fmt.Contains(haystack, needle)Constructors take zero arguments and return stateless prototypes. The form layer calls Clone(parentID, name) to create positioned instances that preserve all configuration.
// Schema definition (ormc generates this).
// input.* kinds get a form input + validation; model.* base kinds
// (e.g. model.Text()) validate only and are never rendered.
var schema = []model.Field{
{Name: "email", Type: input.Email(), NotNull: true},
}
// form.New calls Clone internally, for fields whose Type implements input.Input:
// field.Type.(input.Input).Clone(formID, fieldName) → positioned input with id, name, HTML attributesAll inputs share the same pattern: embed Base, configure Permitted rules, implement the Input interface. Custom inputs can live in your own package — Base, InitBase and all setters are exported.
package myapp
import (
"webtyp.com/fmt"
"webtyp.com/input"
)
// myInput is a custom input that only allows lowercase hex characters.
type myInput struct {
input.Base
}
// MyInput creates a prototype — no arguments.
func MyInput() input.Input {
m := &myInput{}
m.Letters = true
m.Numbers = true
m.Minimum = 1
m.Maximum = 40
m.InitBase("", "", "text")
m.SetPlaceholder("example:", "3f4a1b")
m.SetTitle("Lowercase hex only")
return m
}
func (m *myInput) Validate(value string) error {
// Custom rule: no uppercase letters
for _, c := range value {
if c >= 'A' && c <= 'F' {
return fmt.Err("Character", "Invalid")
}
}
return m.Permitted.Validate(m.FieldName(), value)
}
// Clone creates a positioned copy preserving all configuration.
func (m *myInput) Clone(parentID, name string) input.Input {
c := *m
c.InitBase(parentID, name, "text")
return &c
}The custom input renders with the generic markup for its htmlName
("text" above). Storage defaults by htmlName (number → int,
checkbox → bool, else text); override Storage() on your struct if your
kind needs a different mapping.
Custom inputs can provide their own HTML markup by implementing form.Renderer (see docs/API.md). This allows for complex widgets (color pickers, composite fields) while the form still manages the field container, ID, and validation state.
| Method | Purpose |
|---|---|
InitBase(parentID, name, htmlName) |
Required — sets ID, name, and HTML type |
SetPlaceholder(string) |
HTML placeholder text |
SetTitle(string) |
HTML title (tooltip) |
SetOptions(...fmt.KeyValue) |
Options for select/radio/datalist |
AddAttribute(key, value string) |
Custom extra HTML attributes |
SetRequired(bool) |
HTML required attribute |
SetSkipValidation(bool) |
Skip validation entirely |
Reuse existing inputs to create semantic wrappers:
func Gender() Input {
g := &gender{}
g.InitBase("", "", "radio")
g.SetOptions(
fmt.KeyValue{Key: "m", Value: "Male"},
fmt.KeyValue{Key: "f", Value: "Female"},
)
return g
}