Class: Charming::Presentation::Components::Form::Field

Inherits:
Charming::Presentation::Component show all
Defined in:
lib/charming/presentation/components/form/field.rb

Overview

Field is the abstract base class for Form fields. Subclasses define ‘default_value` and `render_control` (or override `render`); the base class supplies validation, help-line rendering, error-line rendering, and value lookup against the form state.

Direct Known Subclasses

Confirm, Input, Note, Select, Textarea

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from View

#focused?, #layout_assigns

Constructor Details

#initialize(name, label: nil, required: false, validate: nil, help: nil, theme: nil) ⇒ Field

name is the value key (a Symbol). label defaults to a humanized version of name. required enables a “is required” validator. validate is an optional callable (returning nil/true → ok, false → “is invalid”, Array → messages, anything else → stringified). help is an optional muted helper line rendered under the field.



18
19
20
21
22
23
24
25
# File 'lib/charming/presentation/components/form/field.rb', line 18

def initialize(name, label: nil, required: false, validate: nil, help: nil, theme: nil)
  super(theme: theme)
  @name = name.to_sym
  @label = label || humanize(name)
  @required = required
  @validator = validate
  @help = help
end

Instance Attribute Details

#helpObject (readonly)

The field’s name symbol, human-readable label, optional help text, and bound state hash.



12
13
14
# File 'lib/charming/presentation/components/form/field.rb', line 12

def help
  @help
end

#labelObject (readonly)

The field’s name symbol, human-readable label, optional help text, and bound state hash.



12
13
14
# File 'lib/charming/presentation/components/form/field.rb', line 12

def label
  @label
end

#nameObject (readonly)

The field’s name symbol, human-readable label, optional help text, and bound state hash.



12
13
14
# File 'lib/charming/presentation/components/form/field.rb', line 12

def name
  @name
end

#stateObject (readonly)

The field’s name symbol, human-readable label, optional help text, and bound state hash.



12
13
14
# File 'lib/charming/presentation/components/form/field.rb', line 12

def state
  @state
end

Instance Method Details

#bind(state) ⇒ Object

Binds the field to the form’s state hash, ensuring the field’s per-field state and a default value are present.



29
30
31
32
33
# File 'lib/charming/presentation/components/form/field.rb', line 29

def bind(state)
  @state = state
  state[:fields][name] ||= {}
  state[:values][name] = default_value unless state[:values].key?(name)
end

#focusable?Boolean

Subclasses that participate in Tab/Enter navigation return true. Default is true.

Returns:

  • (Boolean)


36
37
38
# File 'lib/charming/presentation/components/form/field.rb', line 36

def focusable?
  true
end

#handle_key(_event) ⇒ Object

Default key handler returns nil (no key handling). Subclasses override.



41
42
43
# File 'lib/charming/presentation/components/form/field.rb', line 41

def handle_key(_event)
  nil
end

#render(active: false) ⇒ Object

Renders the field as a control line prefixed with “>” (active) or “ ” (inactive), optionally followed by the help line and any error lines.



47
48
49
50
51
# File 'lib/charming/presentation/components/form/field.rb', line 47

def render(active: false)
  line = "#{active ? ">" : " "} #{render_control}"
  line = theme.selected.render(line) if active
  [line, help_line, *error_lines].compact.join("\n")
end

#validateObject

Returns an array of validation error messages. Includes “is required” when the field is required and blank, plus any messages produced by the user validator.



55
56
57
58
59
60
# File 'lib/charming/presentation/components/form/field.rb', line 55

def validate
  messages = []
  messages << "is required" if required? && blank?(value)
  messages.concat(validator_messages) if @validator
  messages
end

#valueObject

The current value of this field from the bound state.



63
64
65
# File 'lib/charming/presentation/components/form/field.rb', line 63

def value
  state[:values][name]
end