Documentation
¶
Overview ¶
Package forms composes portable entity forms from detached presentation inputs. Handlers own authorization, parsing, persistence and the meaning of errors.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrFields = errors.New("forms: field names must be nonempty and unique")
ErrFields refuses ambiguous input names and the DOM/source identities they create.
var ErrNamespace = errors.New("forms: namespace must start with a letter and contain only letters, digits, underscores or hyphens")
ErrNamespace reports an unusable instance scope before any example is returned.
Functions ¶
func Control ¶
func Control(p ControlProps) g.Node
Control renders the existing component chosen by the entity widget/type. Its capture retains "field/" plus the schema name and Core's Props contract.
func Example ¶
Example captures the same typed Form and field constructors used at runtime. It returns a presentation candidate; rendering or editing it performs no write. DOM identities and HTMX targets belong to Namespace, never to the source ID.
func MustExample ¶
MustExample is Example for a composition whose field names were already kept distinct by the thing that built the schema. It exists for the generated screens, which render a page and have no channel left to report on: kit/crud derives one name per struct field, falling back to the Go name when the JSON tag is empty, and go vet refuses a struct that repeats a tag, so a schema that reached a mounted route cannot hold two fields of one name.
Reaching the panic therefore means a hand-built entity.Schema — a design invocation, an adapter — named two fields the same. That is a composition bug, and it is said in the same shape regexp.MustCompile and this repository's own component constructors already use it.
func Namespace ¶
Namespace derives a form's DOM scope from the address it posts to. It exists because the two things a generated form's identity has to satisfy pull apart: it must differ from every other form on the page, and it must not change when the same screen re-renders a refused submission — the swap that puts the field errors back targets the id the form was drawn with. An address gives both: one screen posts to one address, and a refused POST is answered by the screen at that same address. A fixed id gave neither, which is why one screen could hold only one generated form.
The answer is always something Example accepts: a letter, a digit, an underscore or a hyphen is kept, everything else is a separator, consecutive separators collapse and a leading separator is dropped, so the identity stays readable in DevTools rather than a run of dashes. Two addresses are given the same identity only where they differ in punctuation alone, and a screen serves one address, so that never puts two forms on one page. A leading digit is prefixed rather than dropped, and an input with nothing usable in it gets a fixed scope. namespace_test.go feeds it the inputs that would break that and checks every byte of every answer.
Types ¶
type ControlProps ¶
ControlProps describes one field's presentation. ID is the trusted DOM identity; leaving it empty uses the component's historical name-derived default. Enclosing forms should use Example, which supplies a distinct identity to every control.
type Field ¶
type Field struct {
Definition entity.Field
Label string
Options []components.SelectOption
}
Field presents an existing entity definition. Label and Options supply display words explicitly; they do not change the definition's names or enum values. Empty labels use the field name, and absent options use the declared enum text.
type Model ¶
type Model struct {
Fields []Field
Values map[string]string
Errors map[string]string
Immutable []string
Detail string
Create bool
}
Model contains a form's already-read values and already-decided field errors. A missing value uses the declared default only on create; an explicit empty value remains empty. ReadOnly fields are omitted, as are immutable create fields.
type Options ¶
type Options struct {
Namespace string
Action, CancelURL, Title string
CancelLabel, SubmitLabel, FailureTitle string
}
Options supplies presentation and command addresses. Namespace is a DOM scope, separate from an example's source identity. Use a unique stable namespace per rendered instance. It must start with an ASCII letter and contain only letters, digits, underscores or hyphens. The resulting form ID is Namespace + "-form".