Class: Superform::Field

Inherits:
Node
  • Object
show all
Includes:
Phlex::Helpers
Defined in:
lib/superform/field.rb

Overview

A Field represents the data associated with a form element. This class provides methods for accessing and modifying the field's value. HTML concerns are all delegated to the DOM object.

Direct Known Subclasses

Rails::Field

Defined Under Namespace

Classes: Kit

Instance Attribute Summary collapse

Attributes inherited from Node

#key, #parent

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(key, parent:, object: nil, value: nil) {|_self| ... } ⇒ Field

Returns a new instance of Field.

Yields:

  • (_self)

Yield Parameters:



13
14
15
16
17
18
19
# File 'lib/superform/field.rb', line 13

def initialize(key, parent:, object: nil, value: nil)
  super key, parent: parent
  @object = object
  @value = value
  @dom = Superform::DOM.new(field: self)
  yield self if block_given?
end

Instance Attribute Details

#domObject (readonly)

Expose these as a reader so they're accessible from the input, label, etc. methods.



11
12
13
# File 'lib/superform/field.rb', line 11

def dom
  @dom
end

#objectObject (readonly)

Expose these as a reader so they're accessible from the input, label, etc. methods.



11
12
13
# File 'lib/superform/field.rb', line 11

def object
  @object
end

Class Method Details

.add_method_to_kit(method_name, kit_class) ⇒ Object



112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/superform/field.rb', line 112

def self.add_method_to_kit(method_name, kit_class)
  return if method_name.to_s.end_with?('=')

  base_methods = (Object.instance_methods + Node.instance_methods +
                 [:dom, :value, :serialize, :assign, :collection, :field, :kit]).to_set
  return if base_methods.include?(method_name)
  return if kit_class.method_defined?(method_name)

  kit_class.define_method(method_name) do |*args, **kwargs, &block|
    result = @field.send(method_name, *args, **kwargs, &block)
    @form.render result
  end
end

.copy_field_methods_to_kit(field_class, kit_class) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/superform/field.rb', line 96

def self.copy_field_methods_to_kit(field_class, kit_class)
  base_methods = (Object.instance_methods + Node.instance_methods +
                 [:dom, :value, :serialize, :assign, :collection, :field, :kit]).to_set

  field_class.instance_methods(false).each do |method_name|
    next if method_name.to_s.end_with?('=')
    next if base_methods.include?(method_name)
    next if kit_class.method_defined?(method_name)

    kit_class.define_method(method_name) do |*args, **kwargs, &block|
      result = @field.send(method_name, *args, **kwargs, &block)
      @form.render result
    end
  end
end

.inherited(subclass) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/superform/field.rb', line 66

def self.inherited(subclass)
  super
  # Create a new Kit class for each Field subclass with true isolation
  # Copy methods from parent Field classes at creation time, not through inheritance
  subclass.const_set(:Kit, Class.new(Field::Kit))

  # Copy all existing methods from the inheritance chain
  field_class = self
  while field_class != Field
    copy_field_methods_to_kit(field_class, subclass::Kit)
    field_class = field_class.superclass
  end
end

.method_added(method_name) ⇒ Object



80
81
82
83
84
85
86
87
88
# File 'lib/superform/field.rb', line 80

def self.method_added(method_name)
  super
  # Skip if this is the base Field class or if we don't have a Kit class yet
  return if self == Field
  return unless const_defined?(:Kit, false)

  # Only add method to THIS class's Kit, not subclasses (isolation)
  add_method_to_kit(method_name, self::Kit)
end

Instance Method Details

#assign(value) ⇒ Object Also known as: value=



30
31
32
33
34
35
36
# File 'lib/superform/field.rb', line 30

def assign(value)
  if @object and @object.respond_to? "#{@key}="
    @object.send "#{@key}=", value
  else
    @value = value
  end
end

#collectionObject

Wraps a field that's an array of values with a bunch of fields that are indexed with the array's index.



41
42
43
# File 'lib/superform/field.rb', line 41

def collection(&)
  @collection ||= FieldCollection.new(field: self, &)
end

#fieldObject

Make the name more obvious for extending or writing docs.



46
47
48
# File 'lib/superform/field.rb', line 46

def field
  self
end

#kit(form) ⇒ Object



90
91
92
# File 'lib/superform/field.rb', line 90

def kit(form)
  self.class::Kit.new(field: self, form: form)
end

#valueObject Also known as: serialize



21
22
23
24
25
26
27
# File 'lib/superform/field.rb', line 21

def value
  if @object and @object.respond_to? @key
    @object.send @key
  else
    @value
  end
end