form

package module
v2.1.1 Latest Latest
Warning

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

Go to latest
Published: Jul 16, 2026 License: MIT Imports: 18 Imported by: 0

README

go-form

A Go library for rendering HTML forms from Go structs using struct tags and Go templates. Supports multiple template styles (Plain, Bootstrap 5, Tailwind CSS) and a wide range of HTML input types.


Features

  • Define forms as Go structs with struct tags for field type, label, placeholder, and more
  • Supports many HTML input types: text, password, email, tel, number, date, color, range, datetime-local, time, week, month, hidden
  • Checkbox, radio, dropdown, and textarea fields
  • Grouping and nested struct support for form sections
  • Built-in template sets: Plain, Bootstrap 5, Tailwind CSS
  • Integrates with html/template via a FuncMap
  • CSRF Protection
  • SortedSelect and SortedMultiSelect for type-safe, mapped dropdowns and multi-selects (see examples)

Installation

go get github.com/donseba/go-form/v2

Quick Start

import (
    "html/template"

    "github.com/donseba/go-form/v2"
)

type ExampleForm struct {
    Username string `form:"input,text" label:"Username" placeholder:"Enter your username" required:"true"`
    Password string `form:"input,password" label:"Password" placeholder:"Enter your password" required:"true"`
    Email    string `form:"input,email" label:"Email" placeholder:"Enter your email" required:"true"`
    Age      int    `form:"input,number" label:"Age" placeholder:"Enter your age" step:"1"`
}

f := form.NewForm()
funcMap := f.FuncMap()
_ = template.Must(template.New("form").Funcs(funcMap).Parse(`{{ form_render .Form nil }}`))

Supported Templates

Template Name Description
templates.Plain Plain HTML, minimal styles
templates.BootstrapV5 Bootstrap 5 form styles
templates.TailwindV3 Tailwind CSS v3 styles

Supported Input Fields & Options

Field Type / Tag Example Description Options (Struct Tags)
form:"input,text" Text input label, placeholder, required, maxlength
form:"input,password" Password input label, placeholder, required
form:"input,email" Email input label, placeholder, required
form:"input,number" Number input label, placeholder, required, min, max, step
form:"input,date" Date input label, placeholder, required
form:"input,datetime-local" DateTime input label, placeholder, required
form:"input,time" Time input label, placeholder, required
form:"input,week" Week input label, placeholder, required
form:"input,month" Month input label, placeholder, required
form:"input,color" Color input label, placeholder, required
form:"input,range" Range input label, min, max, step
form:"input,hidden" Hidden input value
form:"input,search" Search input label, placeholder
form:"input,url" URL input label, placeholder
form:"input,tel" Telephone input label, placeholder
form:"input,image" Image input label, src, alt
form:"checkbox" Checkbox label, required
form:"radios" Radio group label, values (e.g. a:A;b:B), required
form:"dropdown" Dropdown/select label, values (e.g. a:A;b:B), required
form:"multicheckbox" Multi-checkbox group label, values (e.g. a:A;b:B), required

Other supported tags:

  • legend — For grouping/nested structs (section title)
  • description — Field description/help text
  • maxLength — Maximum length for textarea or string input
  • class — Custom CSS class for the field
  • data — Custom data attributes (e.g., data="custom:value,foo:bar,baz:qux")
  • translate — Enable translation for enum values (e.g., translate:"true" for Enumerator fields)

Validation

Built-in Validation
  • required: Ensures the field is not empty.
  • min, max, step: For numeric fields, enforces minimum, maximum, and step values.
  • minLength, maxLength: For string/textarea fields, enforces minimum and maximum character count (Unicode-aware).
  • values: For radios/dropdowns, ensures the value is one of the allowed options.
  • Email format: Checks for a valid email address format (basic @ check).
  • Enumerator, Mapper, SortedMapper: If a field implements one of these interfaces, the value must be present in the allowed set returned by Enum(), Mapper(), or SortedMapper().
Using Enumerator, Mapper, and SortedMapper Interfaces

For enum values, implement Enumerator:

type Status string
func (s Status) Enum() []any { return []any{"active", "inactive"} }

type MyForm struct {
    Status Status `form:"dropdown" label:"Status"`
}

For key-value pairs, use Mapper (unordered) or SortedMapper (ordered):

type ColorMap string
func (c ColorMap) Mapper() map[string]string {
    return map[string]string{"red": "Red", "blue": "Blue"}
}

// For ordered pairs, implement SortedMapper with []SortedMap
Custom Validation

You can add your own validation logic using the validate struct tag and by registering a custom validation function:

// 1. Define your validation function (must return form.FieldErrors)
func isHexColor(val any, field reflect.StructField) form.FieldErrors { /* ... */ }

// 2. Register it with your Form instance
f.RegisterValidationMethod("isHexColor", isHexColor)

// 3. Use it in your struct
type MyForm struct {
    Color string `form:"input,text" label:"Color" validate:"isHexColor"`
}

// 4. Call f.ValidateForm(&myForm) to run both built-in and custom validations

Custom validators can be chained with commas in the validate tag. All errors are collected and can be rendered in your template.


Translation / Internationalization

go-form supports translation of form labels, error messages, and other UI text. You can provide your own translation function and a Localizer implementation to render forms in different languages or customize the wording for your application.

How to Use
  1. Create a translation function: This function receives a Localizer, a key, and optional arguments, and returns the translated string.
  2. Implement a Localizer: This determines the current locale (e.g., from the user session or request).
  3. Create the form with translation support: Use form.NewTranslatedForm(template, translateFunc).
  4. Pass your Localizer when rendering or validating: The form will use your translation function and Localizer to fetch translations.
// Example translation function and Localizer
var translations = map[string]map[string]string{
    "en": {"Name": "Name", "form.validation.required": "is required"},
    "it": {"Name": "Nome", "form.validation.required": "è obbligatorio"},
}

type MyLocalizer struct { Locale string }
func (l MyLocalizer) GetLocale() string { return l.Locale }

func myTranslate(loc form.Localizer, key string, args ...any) string {
    locale := "en"
    if l, ok := loc.(MyLocalizer); ok {
        locale = l.Locale
    }
    msg := key
    if m, ok := translations[locale]; ok {
        if t, ok := m[key]; ok {
            msg = t
        }
    }
    if len(args) > 0 {
        return fmt.Sprintf(msg, args...)
    }
    return msg
}

f := form.NewTranslatedForm(templates.Plain, myTranslate)
// When rendering or validating, pass your Localizer:
loc := MyLocalizer{Locale: "it"}
// ...

See the example in example/translation/main.go for a complete usage demonstration.

Translating Enum Values

By default, enum values display as-is. To enable translation, add translate:"true":

type Status string
func (s Status) Enum() []any { return []any{"active", "inactive"} }

type MyForm struct {
    Status Status `form:"dropdown" label:"Status" translate:"true"`
}

To enable translation for all enums by default, set the global variable:

import "github.com/donseba/go-form/v2"

func init() {
    form.DefaultEnumTranslation = true  // All enums will be translatable by default
}

Individual fields can still opt-out using translate:"false". Translation keys follow the format enum||{TypeName}.{value}:

var translations = map[string]map[string]string{
    "en": {"enum||Status.active": "Active", "enum||Status.inactive": "Inactive"},
    "it": {"enum||Status.active": "Attivo", "enum||Status.inactive": "Inattivo"},
}

Custom Form Attributes

You can set custom HTML attributes on forms (e.g., hx-post, data-*, etc.) using the Attributes field in your form struct:

form := &FormField{
    // ...other fields...
    Attributes: map[string]string{
        "hx-post": "/some-url",
        "data-custom": "value",
    },
}
Input Groups (Prepend/Append)

You can prepend or append content to input fields using the group tag. This is supported in all template sets (Plain, Bootstrap 5, Tailwind CSS):

type ExampleForm struct {
    Username string `form:"input,text" label:"Username" group:"@,.com"`
}

This will render an input with @ before and .com after the field, styled according to the selected template.


CSRF Protection

go-form includes built-in CSRF (Cross-Site Request Forgery) protection for your forms. This prevents attackers from tricking users into submitting unauthorized requests.

Basic Usage
  1. Create a form renderer which adds a default CSRF protection by default:

    formRenderer := form.NewForm(templates.BootstrapV5)
    
  2. Apply the CSRF middleware to your handlers:

    // With standard http.ServeMux:
    protectedHandler := formRenderer.CSRFMiddleware()(yourHandler) // <-- wrap your handler
    mux.Handle("/", protectedHandler)
    
    // With Chi router:
    import "github.com/go-chi/chi/v5"
    
    router := chi.NewRouter()
    router.Use(formRenderer.CSRFMiddleware()) // <-- load the middleware
    
  3. Associate the form metadata with the model before rendering. This also injects the request's CSRF token:


  loginForm := LoginForm{Email: "name@example.com"}
  renderModel := form.WithRequestInfo(r, loginForm, form.Info{
    Target:     "/login",
    Method:     "post",
    SubmitText: "Log In",
  })

WithInfo works when CSRF is not needed. WithContextInfo is useful in a rendering service that receives a context.Context rather than an HTTP request. These wrappers let application- or provider-owned structs use full form metadata without embedding form.Info or changing their field names.

Models that already embed form.Info remain supported. For those models, InjectCSRFToken can still populate the embedded metadata directly.

The middleware automatically:

  • Generates a secure random token for each form
  • Validates the token on submission
  • Refreshes tokens after each submission
  • Rejects requests with missing or invalid tokens
Custom Error Handling

By default, CSRF validation failures return HTTP error responses. For a better user experience, you can provide custom error handling:

options := form.CSRFOptions{
  ErrorHandler: func(w http.ResponseWriter, r *http.Request, err error) {
    switch {
      case errors.Is(err, csrf.ErrTokenMismatch):
      http.Error(w, "Invalid CSRF token", http.StatusForbidden)
      case errors.Is(err, csrf.ErrTokenExpired):
      http.Error(w, "CSRF token expired", http.StatusForbidden)
      case errors.Is(err, csrf.ErrKeyOrTokenEmpty):
      http.Error(w, "CSRF token or session ID is empty", http.StatusBadRequest)
      case errors.Is(err, csrf.ErrTokenNotFound):
      http.Error(w, "CSRF token not found", http.StatusBadRequest)
      default:
      http.Error(w, "CSRF validation error: "+err.Error(), http.StatusBadRequest)
    }
  },
}

// Use the custom options
protectedHandler := formRenderer.CSRFMiddlewareWithOptions(options)(yourHandler)
Alternative CSRF Stores

The default in-memory CSRF store is suitable for single-server applications. For production or distributed environments, you can implement a custom CSRFStore that uses Redis, a database, or another shared storage mechanism:

// Example Redis CSRF Store implementation
type RedisCSRFStore struct {
    client *redis.Client
    prefix string
    ttl    time.Duration
}

func (s *RedisCSRFStore) Store(key, token string) error {
    return s.client.Set(ctx, s.prefix+key, token, s.ttl).Err()
}

func (s *RedisCSRFStore) Get(key string) (string, error) {
    val, err := s.client.Get(ctx, s.prefix+key).Result()
    if err == redis.Nil {
        return "", csrf.ErrTokenNotFound
    }
    return val, err
}

// ... implement other required methods ...

// Then use it with your form:
store := &RedisCSRFStore{
    client: redisClient,
    prefix: "csrf:",
    ttl:    30 * time.Minute,
}
formRenderer.SetCSRFStore(store)

See the example in example/csrf/main.go for a complete usage demonstration.


SortedSelect and SortedMultiSelect

SortedSelect and SortedMultiSelect are generic types for type-safe, mapped dropdowns and multi-selects with custom key types. They support form mapping, validation, database integration, and JSON serialization.

  • SortedSelect is for single-value dropdowns (e.g., DepartmentID form.SortedSelect[int64]).
  • SortedMultiSelect is for multi-value selections (e.g., DepartmentsMulti form.SortedMultiSelect[int64]).
  • Both support any comparable Go type as the key: int, int64, string, float64, uuid.UUID, time.Time, etc.
  • They work seamlessly with form rendering, validation, and database/sql or JSON marshalling.

Minimal usage example:

import "github.com/donseba/go-form/v2"

// Single select
DepartmentID form.SortedSelect[int64] `form:"dropdown" label:"Department"`

// Multi select
DepartmentsMulti form.SortedMultiSelect[int64] `form:"multicheckbox" label:"Departments"`

// Initialize with a source map
form.NewSortedSelect(map[int64]string{1: "HR", 2: "IT"})
form.NewSortedMultiSelect(map[int64]string{1: "HR", 2: "IT"})

For advanced usage, see example/sortedselect/main.go — covers single and multi-select fields, supported key types, pre-filled and user-submitted values, validation, error handling, JSON and DB integration.


License

This project is licensed under the MIT License - see the LICENSE file for details.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrMapFormNotPointer = &MapFormError{"dst must be a pointer to struct"}
	ErrMapFormNotStruct  = &MapFormError{"dst must be a pointer to struct"}
)
View Source
var (
	DefaultSubmitText      = "Submit"
	DefaultEnumTranslation = false // Set to true to enable translation for all enums by default
)
View Source
var (
	TranslationKeyRequired                      = "form||Validation required"
	TranslationKeyMin                           = "form||Value should be greater than or equal to %v"
	TranslationKeyMax                           = "form||Value should be less than or equal to %v"
	TranslationKeyMaxLength                     = "form||Value should not exceed %d characters"
	TranslationKeyMinLength                     = "form||Value should be at least %d characters"
	TranslationKeyInvalidValue                  = "form||Invalid value '%s' provided"
	TranslationKeyInvalidEmail                  = "form||Invalid email format"
	TranslationKeyInvalidEnum                   = "form||Invalid enum value '%s' provided"
	TranslationKeyInvalidMapper                 = "form||Invalid mapper value '%s' provided"
	TranslationKeyInvalidSortedMapper           = "form||Invalid sorted mapper value '%s' provided"
	TranslationKeyPattern                       = "form||Value does not match the required pattern '%s'"
	TranslationKeyURL                           = "form||Invalid URL format"
	TranslationKeyBool                          = "form||Value should be either true or false"
	TranslationKeyZero                          = "form||Value should be zero"
	TranslationKeyMinItems                      = "form||Value should have at least %d items"
	TranslationKeyMaxItems                      = "form||Value should have at most %d items"
	TranslationKeyPrefix                        = "form||Value should start with '%s'"
	TranslationKeySuffix                        = "form||Value should end with '%s'"
	TranslationKeyContains                      = "form||Value should contain '%s'"
	TranslationKeyStep                          = "form||Value should be a multiple of %f"
	TranslationKeyCSRFTokenMissing              = "form||CSRF token is missing"
	TranslationKeyCSRFTokenInvalid              = "form||Invalid CSRF token"
	TranslationKeyCSRFTokenError                = "form||Error processing CSRF token"
	TranslationKeySortedSelectNotFound          = "form||SortedSelect: value '%v' not found in source"
	TranslationKeySortedSelectKeyNotFound       = "form||SortedSelect: key '%s' not found in source"
	TranslationKeySortedSelectSourceNil         = "form||SortedSelect: source map is nil"
	TranslationKeySortedSelectTypeError         = "form||Cannot assign or convert value of type %T to %s"
	TranslationKeySortedSelectUnmarshalNotFound = "form||SortedSelect: value '%v' not found in source during unmarshal"
)
View Source
var (
	DefaultCSRFField = "_csrf"
)

CSRF errors

Functions

func GetCSRFToken

func GetCSRFToken(r *http.Request) (string, bool)

GetCSRFToken retrieves the CSRF token from the request context

func HasFields added in v2.1.0

func HasFields(model any) bool

HasFields reports whether model contains at least one renderable field. Form metadata does not count as a field.

func InjectCSRFToken

func InjectCSRFToken(r *http.Request, info *Info)

InjectCSRFToken adds the CSRF token to the form Info struct

func InjectCSRFTokenContext added in v2.1.0

func InjectCSRFTokenContext(ctx context.Context, info *Info)

InjectCSRFTokenContext adds the CSRF token from ctx to the form Info struct. It is useful when rendering happens below the HTTP controller layer.

func MapForm

func MapForm(r *http.Request, dst any, prefixes ...string) error

MapForm maps form values from an http.Request to a struct based on the `name` tag. Only exported fields are set. Supports string, int, float64, and bool fields.

func WeekStringToTime

func WeekStringToTime(weekStr string) (time.Time, error)

Types

type CSRFOptions

type CSRFOptions struct {
	// ErrorHandler lets you customize error handling instead of returning HTTP errors
	ErrorHandler func(w http.ResponseWriter, r *http.Request, err error)
}

CSRFOptions configures how the CSRF middleware behaves

func DefaultCSRFOptions

func DefaultCSRFOptions() CSRFOptions

DefaultCSRFOptions returns the default options for CSRF protection

type DefaultLocalizer

type DefaultLocalizer struct{}

func (*DefaultLocalizer) GetLocale

func (d *DefaultLocalizer) GetLocale() string

type Enumerator

type Enumerator interface{ Enum() []any }

type FieldError

type FieldError interface {
	FieldError() (field, err string)
}

type FieldErrors

type FieldErrors []FieldError

type FieldValidationError

type FieldValidationError struct {
	Field string
	Err   string
}

FieldValidationError represents a validation error for a specific field.

func (FieldValidationError) Error

func (e FieldValidationError) Error() string

Error implements the error interface for FieldValidationError.

func (FieldValidationError) FieldError

func (e FieldValidationError) FieldError() (field, err string)

FieldError returns the field and error message.

type Form

type Form struct {
	// contains filtered or unexported fields
}

func NewForm

func NewForm() *Form

NewForm creates a new form without translation support.

func NewTranslatedForm

func NewTranslatedForm(translationFunc TranslationFunc) *Form

NewTranslatedForm creates a new form with translation support.

func (*Form) CSRFMiddleware

func (f *Form) CSRFMiddleware() func(next http.Handler) http.Handler

CSRFMiddleware creates middleware for CSRF protection with default options

func (*Form) CSRFMiddlewareWithOptions

func (f *Form) CSRFMiddlewareWithOptions(options CSRFOptions) func(next http.Handler) http.Handler

CSRFMiddlewareWithOptions creates middleware for CSRF protection with custom options

func (*Form) FuncMap

func (f *Form) FuncMap() template.FuncMap

func (*Form) GetCSRFStore

func (f *Form) GetCSRFStore() csrf.Store

GetCSRFStore returns the CSRF store

func (*Form) GetValidationMethod

func (f *Form) GetValidationMethod(name string) (ValidationFunc, bool)

func (*Form) HasCSRFStore

func (f *Form) HasCSRFStore() bool

HasCSRFStore checks if the form has a CSRF store

func (*Form) RegisterValidationMethod

func (f *Form) RegisterValidationMethod(name string, fn ValidationFunc)

func (*Form) SetCSRFStore

func (f *Form) SetCSRFStore(store csrf.Store)

SetCSRFStore sets the CSRF store for the Form

func (*Form) SetTheme

func (f *Form) SetTheme(name string)

SetTheme selects which gohtml theme is used for rendering.

func (*Form) ValidateForm

func (f *Form) ValidateForm(form any) FieldErrors

func (*Form) ValidateFormLocalized

func (f *Form) ValidateFormLocalized(form any, loc Localizer) FieldErrors

type Info

type Info struct {
	Target     string `json:"target,omitempty"`
	Method     string `json:"method,omitempty"`
	SubmitText string `json:"submit,omitempty"`

	// CancelTarget enables an optional cancel action rendered by templates (as a link).
	// When empty, no cancel control is rendered.
	CancelTarget string `json:"cancel_target,omitempty"`
	// CancelText is the label for the cancel action. If empty and CancelTarget is set,
	// templates should fall back to a sensible default (e.g. "Cancel").
	CancelText string `json:"cancel_text,omitempty"`

	Attributes map[string]string `json:"attributes,omitempty"`
	CsrfValue  string            `json:"csrf_value,omitempty"` // CSRF token value
	CsrfField  string            `json:"csrf_field,omitempty"` // Name of the CSRF field (defaults to "_csrf")
}

type Localizer

type Localizer = types.Localizer

Localizer is the public interface used by go-form for translations.

It is an alias to types.Localizer to keep the API ergonomic and backwards-compatible with code that expects form.Localizer.

type MapFormError

type MapFormError struct {
	// contains filtered or unexported fields
}

func (*MapFormError) Error

func (e *MapFormError) Error() string

type Mapper

type Mapper interface {
	Mapper() map[string]string
	String() string
}

type MultiSelectGetter

type MultiSelectGetter interface {
	GetKeysAsStrings() []string
}

MultiSelectGetter provides a unified way to get selected keys as strings for all multi-select types.

type RenderModel added in v2.1.0

type RenderModel struct {
	Info  Info
	Model any
}

RenderModel associates form metadata with a model without requiring the model's concrete type to embed Info. Construct it with WithInfo, WithContextInfo, or WithRequestInfo.

func WithContextInfo added in v2.1.0

func WithContextInfo(ctx context.Context, model any, info Info) RenderModel

WithContextInfo associates form metadata with a model and injects any CSRF token available in ctx.

func WithInfo added in v2.1.0

func WithInfo(model any, info Info) RenderModel

WithInfo associates form metadata with a model for rendering. The model's fields keep their original names and nesting; RenderModel is transparent to the transformer.

func WithRequestInfo added in v2.1.0

func WithRequestInfo(r *http.Request, model any, info Info) RenderModel

WithRequestInfo associates form metadata with a model and injects any CSRF token available on r.

type SortedMap

type SortedMap interface {
	Key() string
	Value() string
}

type SortedMapper

type SortedMapper interface {
	String() string
	SortedMapper() []SortedMap
}

SortedMapper is a new addition to provide sorted key value pairs

type SortedMultiSelect

type SortedMultiSelect[T comparable] struct {
	// contains filtered or unexported fields
}

SortedMultiSelect is a generic helper for multi-select dropdowns with custom key types. Holds a slice of selected values and a map of key->label.

func NewSortedMultiSelect

func NewSortedMultiSelect[T comparable](source map[T]string) SortedMultiSelect[T]

func (SortedMultiSelect[T]) Get

func (sms SortedMultiSelect[T]) Get() []T

Get returns the current selected values.

func (SortedMultiSelect[T]) GetKeysAsStrings

func (sms SortedMultiSelect[T]) GetKeysAsStrings() []string

GetKeysAsStrings returns the selected keys as strings.

func (SortedMultiSelect[T]) MarshalJSON

func (sms SortedMultiSelect[T]) MarshalJSON() ([]byte, error)

MarshalJSON outputs {"values":..., "source":...} with string keys for source

func (*SortedMultiSelect[T]) Scan

func (sms *SortedMultiSelect[T]) Scan(val any) error

Scan implements database/sql.Scanner for []T.

func (*SortedMultiSelect[T]) Set

func (sms *SortedMultiSelect[T]) Set(vals []T) error

Set sets the selected values, ensuring all exist in Source.

func (*SortedMultiSelect[T]) SetFromKeys

func (sms *SortedMultiSelect[T]) SetFromKeys(keys []string) error

SetFromKeys sets the selected values from a slice of string keys (as submitted by forms).

func (*SortedMultiSelect[T]) SetSource

func (sms *SortedMultiSelect[T]) SetSource(source map[T]string)

SetSource sets or updates the source map for SortedMultiSelect.

func (SortedMultiSelect[T]) SortedMapper

func (sms SortedMultiSelect[T]) SortedMapper() []SortedMap

SortedMapper returns entries sorted by key string representation.

func (SortedMultiSelect[T]) Source

func (sms SortedMultiSelect[T]) Source() map[T]string

Source returns a copy of the internal source map for read-only access.

func (SortedMultiSelect[T]) String

func (sms SortedMultiSelect[T]) String() string

String returns the selected values as a comma-separated string.

func (*SortedMultiSelect[T]) UnmarshalJSON

func (sms *SortedMultiSelect[T]) UnmarshalJSON(data []byte) error

UnmarshalJSON restores values and Source, validates values

func (*SortedMultiSelect[T]) Value

func (sms *SortedMultiSelect[T]) Value() (any, error)

Value returns the selected values for DB storage.

type SortedSelect

type SortedSelect[T comparable] struct {
	// contains filtered or unexported fields
}

SortedSelect is a generic helper that holds a typed key value and a map of key->label It implements SortedMapper (value receiver) and a SetFromKey method (pointer receiver) so MapForm can set the selected value from the posted key string. T must be comparable to be used as map key.

func NewSortedSelect

func NewSortedSelect[T comparable](source map[T]string) SortedSelect[T]

func (SortedSelect[T]) Get

func (ss SortedSelect[T]) Get() T

Get returns the current value of the SortedSelect field (typed as T)

func (SortedSelect[T]) MarshalJSON

func (ss SortedSelect[T]) MarshalJSON() ([]byte, error)

MarshalJSON outputs {"value":..., "source":...} with string keys for source

func (*SortedSelect[T]) Scan

func (ss *SortedSelect[T]) Scan(val any) error

func (*SortedSelect[T]) Set

func (ss *SortedSelect[T]) Set(val T) error

Set sets the value of the SortedSelect field, ensuring it exists in Source if Source is not nil

func (*SortedSelect[T]) SetFromKey

func (ss *SortedSelect[T]) SetFromKey(key string) error

SetFromKey sets the value from a string key (as submitted by forms)

func (*SortedSelect[T]) SetSource

func (ss *SortedSelect[T]) SetSource(source map[T]string)

SetSource sets or updates the source map for SortedSelect

func (SortedSelect[T]) SortedMapper

func (ss SortedSelect[T]) SortedMapper() []SortedMap

SortedMapper returns entries sorted by key string representation Uses fmt.Sprint to produce string representations of keys (no converters required).

func (SortedSelect[T]) Source

func (ss SortedSelect[T]) Source() map[T]string

Source returns a copy of the internal source map for read-only access

func (SortedSelect[T]) String

func (ss SortedSelect[T]) String() string

String returns the current value as a string using fmt.Sprint (no converters required)

func (*SortedSelect[T]) UnmarshalJSON

func (ss *SortedSelect[T]) UnmarshalJSON(data []byte) error

UnmarshalJSON restores value and Source, validates value

func (*SortedSelect[T]) Value

func (ss *SortedSelect[T]) Value() (any, error)

type SortedSelectError

type SortedSelectError struct {
	Key  string
	Args []any
}

SortedSelectError is a structured error for translation Holds the translation key and arguments for formatting Implements error interface Usage: return SortedSelectError{Key: key, Args: args}

func (SortedSelectError) Error

func (e SortedSelectError) Error() string

type Transformer

type Transformer struct {
	Fields []types.FormField `json:"fields"`
}

func NewTransformer

func NewTransformer(model interface{}) (*Transformer, error)

func (*Transformer) JSON

func (t *Transformer) JSON() json.RawMessage

type TranslationFunc

type TranslationFunc func(loc types.Localizer, key string, args ...any) string

type ValidationFunc

type ValidationFunc func(fieldValue any, fieldStruct reflect.StructField) FieldErrors

Directories

Path Synopsis
example
csrf command
sortedselect command
templates command
themes command
translation command
validation command

Jump to

Keyboard shortcuts

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