Sign inDemoInstall

Package Overview
File Explorer

Install Socket

Protect your apps from supply chain attacks


Package form implements primitives that reduce form boilerplate by allowing the caller to specify their fields exactly once. All values are processed via a chain of transformations that map text into a structured value, and visa versa. Each transformation is encapsulated in a `form.Value` implementation, for instance a `value.Int` will transform text into a Go integer and signal any errors that occur during that transformation. Forms are initialized once with all the fields via a call to `form.Load`. Each field binds an input to a value. By contention, value objects depend on pointer variables, this means you can simply point into a predefined "model" struct. Once the form is submitted, the model will contain the validated values ready to use. However this is only a convention, a value object can arbitrarily handle it's internal state. The following is an example of one way to use the form:


Version published


# form

[![Go Reference](](

Primitives for specifying forms.

The fundamental idea explored here is in separating form concerns.
The three core abstractions are the `Form`, the `Value` and the `Input`.
`Value` and `Input` combine together into a `Field`.

- `Input` abstracts the interactible graphical widget that accepts input.
- `Value` abstracts the transformation of text to structured data.
- `Field` maps an `Input` to a `Value`.
- `Form` provides a consistent api for handling a group of fields, namely batch and realtime validation.

## Status

This repo is experimental, and does not have a stable interface.

Ideally form initialization would be fully declarative, where the zero value is directly usable.
However it's not clear how to achieve such an api.

Some potential avenues to explore:

- code generation: take a struct definition and generate the form code.
- reflection: introspect a struct definition and generate `form.Field`s on the fly.

## Use

Since the api is experimental, there is no "idiomatic usage".

Fundamentally, a form binds inputs to values and there are numerous ways to compose it.

This is an example of one way to use the package: one-time initialization that you can call in an
update function once per frame.

type Person struct {
    Age    int
    Name   string
    Salary float64

type PersonForm struct {
    // Model contains the structured data.
    Model Person
    // Inputs contains the input state.
    Inputs struct {
        Age    component.TextField
        Name   component.TextField
        Salary component.TextField
    init sync.Once

func (pf *PersonForm) Update() {
    pf.init.Do(func() {
                Value: value.Int{Value: &pf.Model.Age, Default: 18},
                Input: &pf.Inputs.Age,
                Value: value.Required{value.Text{Value: &pf.Model.Name, Default: ""}},
                Input: &pf.Inputs.Name,
                Value: value.Float{Value: &pf.Model.Salary, Default: 0},
                Input: &pf.Inputs.Salary,


Last updated on 30 Jun 2021

Did you know?

Socket installs a GitHub app to automatically flag issues on every pull request and report the health of your dependencies. Find out what is inside your node modules and prevent malicious activity before you update the dependencies.


Related posts

SocketSocket SOC 2 Logo


  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.

  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc