superform 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +100 -3
- data/CLAUDE.md +46 -0
- data/Gemfile.lock +6 -1
- data/README.md +208 -75
- data/examples/basic_form.rb +21 -0
- data/examples/checkbox_form.rb +28 -0
- data/examples/date_time_form.rb +18 -0
- data/examples/example_form.rb +10 -0
- data/examples/select_form.rb +26 -0
- data/examples/special_inputs_form.rb +23 -0
- data/examples/textarea_form.rb +15 -0
- data/lib/generators/superform/install/templates/base.rb +33 -7
- data/lib/superform/dom.rb +13 -1
- data/lib/superform/field.rb +14 -31
- data/lib/superform/rails/choices/choice.rb +39 -0
- data/lib/superform/rails/choices/mapper.rb +41 -0
- data/lib/superform/rails/choices.rb +6 -0
- data/lib/superform/rails/components/base.rb +9 -2
- data/lib/superform/rails/components/checkbox.rb +34 -7
- data/lib/superform/rails/components/checkboxes.rb +38 -0
- data/lib/superform/rails/components/datalist.rb +34 -0
- data/lib/superform/rails/components/input.rb +1 -1
- data/lib/superform/rails/components/label.rb +1 -1
- data/lib/superform/rails/components/radio.rb +21 -0
- data/lib/superform/rails/components/radios.rb +38 -0
- data/lib/superform/rails/components/select.rb +52 -8
- data/lib/superform/rails/field.rb +91 -44
- data/lib/superform/version.rb +1 -1
- data/server/components/breadcrumb.rb +11 -0
- data/server/components/form_card.rb +13 -0
- data/server/components/layout.rb +23 -0
- data/server/controllers/forms_controller.rb +94 -0
- data/server/models/example.rb +31 -0
- data/server/public/styles.css +282 -0
- data/server/rails.rb +56 -0
- data/superform.gemspec +37 -0
- metadata +26 -4
- data/lib/superform/rails/option_mapper.rb +0 -36
data/lib/superform/dom.rb
CHANGED
|
@@ -3,6 +3,12 @@ module Superform
|
|
|
3
3
|
# norms that were established by Rails. These can be used outsidef or Rails in
|
|
4
4
|
# other Ruby web frameworks since it has now dependencies on Rails.
|
|
5
5
|
class DOM
|
|
6
|
+
DELIMITER = "_"
|
|
7
|
+
|
|
8
|
+
def self.join(*segments)
|
|
9
|
+
segments.join(DELIMITER)
|
|
10
|
+
end
|
|
11
|
+
|
|
6
12
|
def initialize(field:)
|
|
7
13
|
@field = field
|
|
8
14
|
end
|
|
@@ -17,7 +23,7 @@ module Superform
|
|
|
17
23
|
# them with a `_` for a DOM ID. One limitation of this approach is if multiple forms
|
|
18
24
|
# exist on the same page, the ID may be duplicate.
|
|
19
25
|
def id
|
|
20
|
-
lineage.map(&:key)
|
|
26
|
+
self.class.join(*lineage.map(&:key))
|
|
21
27
|
end
|
|
22
28
|
|
|
23
29
|
# The `name` attribute of a node, which is influenced by Rails (not sure where Rails got
|
|
@@ -29,6 +35,12 @@ module Superform
|
|
|
29
35
|
names.map { |name| "[#{name}]" }.unshift(root).join
|
|
30
36
|
end
|
|
31
37
|
|
|
38
|
+
# Returns the name with `[]` appended for array/multiple value fields.
|
|
39
|
+
# Used by multiple selects, checkbox groups, etc.
|
|
40
|
+
def array_name
|
|
41
|
+
"#{name}[]"
|
|
42
|
+
end
|
|
43
|
+
|
|
32
44
|
# Emit the id, name, and value in an HTML tag-ish that doesnt have an element.
|
|
33
45
|
def inspect
|
|
34
46
|
"<id=#{id.inspect} name=#{name.inspect} value=#{value.inspect}/>"
|
data/lib/superform/field.rb
CHANGED
|
@@ -3,7 +3,12 @@ module Superform
|
|
|
3
3
|
# methods for accessing and modifying the field's value. HTML concerns are all
|
|
4
4
|
# delegated to the DOM object.
|
|
5
5
|
class Field < Node
|
|
6
|
-
|
|
6
|
+
# Helpful for overriding methods in the `input`, `email`, `label`, etc. calls.
|
|
7
|
+
include Phlex::Helpers
|
|
8
|
+
|
|
9
|
+
# Expose these as a reader so they're accessible from the `input`, `label`,
|
|
10
|
+
# etc. methods.
|
|
11
|
+
attr_reader :dom, :object
|
|
7
12
|
|
|
8
13
|
def initialize(key, parent:, object: nil, value: nil)
|
|
9
14
|
super key, parent: parent
|
|
@@ -42,28 +47,6 @@ module Superform
|
|
|
42
47
|
self
|
|
43
48
|
end
|
|
44
49
|
|
|
45
|
-
# A helper, borrowed from Phlex, that makes it easy to "grab" values
|
|
46
|
-
# passed into a method that are reserved keywords. For example, this
|
|
47
|
-
# would throw a syntax error because `class` and `end` are reserved:
|
|
48
|
-
#
|
|
49
|
-
# def foo(end:, class:)
|
|
50
|
-
# puts class
|
|
51
|
-
# puts end
|
|
52
|
-
# end
|
|
53
|
-
#
|
|
54
|
-
# So you "grab" them like this:
|
|
55
|
-
# def foo(end:, class:)
|
|
56
|
-
# puts grab(end:)
|
|
57
|
-
# puts grab(class:)
|
|
58
|
-
# end
|
|
59
|
-
private def grab(**bindings)
|
|
60
|
-
if bindings.size > 1
|
|
61
|
-
bindings.values
|
|
62
|
-
else
|
|
63
|
-
bindings.values.first
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
|
|
67
50
|
# High-performance Kit proxy that wraps field methods with form.render calls.
|
|
68
51
|
# Uses Ruby class hooks to define methods at the class level for maximum speed:
|
|
69
52
|
# - Methods are defined once per Field class, not per Kit instance
|
|
@@ -85,7 +68,7 @@ module Superform
|
|
|
85
68
|
# Create a new Kit class for each Field subclass with true isolation
|
|
86
69
|
# Copy methods from parent Field classes at creation time, not through inheritance
|
|
87
70
|
subclass.const_set(:Kit, Class.new(Field::Kit))
|
|
88
|
-
|
|
71
|
+
|
|
89
72
|
# Copy all existing methods from the inheritance chain
|
|
90
73
|
field_class = self
|
|
91
74
|
while field_class != Field
|
|
@@ -99,7 +82,7 @@ module Superform
|
|
|
99
82
|
# Skip if this is the base Field class or if we don't have a Kit class yet
|
|
100
83
|
return if self == Field
|
|
101
84
|
return unless const_defined?(:Kit, false)
|
|
102
|
-
|
|
85
|
+
|
|
103
86
|
# Only add method to THIS class's Kit, not subclasses (isolation)
|
|
104
87
|
add_method_to_kit(method_name, self::Kit)
|
|
105
88
|
end
|
|
@@ -111,14 +94,14 @@ module Superform
|
|
|
111
94
|
private
|
|
112
95
|
|
|
113
96
|
def self.copy_field_methods_to_kit(field_class, kit_class)
|
|
114
|
-
base_methods = (Object.instance_methods + Node.instance_methods +
|
|
97
|
+
base_methods = (Object.instance_methods + Node.instance_methods +
|
|
115
98
|
[:dom, :value, :serialize, :assign, :collection, :field, :kit]).to_set
|
|
116
|
-
|
|
99
|
+
|
|
117
100
|
field_class.instance_methods(false).each do |method_name|
|
|
118
101
|
next if method_name.to_s.end_with?('=')
|
|
119
102
|
next if base_methods.include?(method_name)
|
|
120
103
|
next if kit_class.method_defined?(method_name)
|
|
121
|
-
|
|
104
|
+
|
|
122
105
|
kit_class.define_method(method_name) do |*args, **kwargs, &block|
|
|
123
106
|
result = @field.send(method_name, *args, **kwargs, &block)
|
|
124
107
|
@form.render result
|
|
@@ -128,12 +111,12 @@ module Superform
|
|
|
128
111
|
|
|
129
112
|
def self.add_method_to_kit(method_name, kit_class)
|
|
130
113
|
return if method_name.to_s.end_with?('=')
|
|
131
|
-
|
|
132
|
-
base_methods = (Object.instance_methods + Node.instance_methods +
|
|
114
|
+
|
|
115
|
+
base_methods = (Object.instance_methods + Node.instance_methods +
|
|
133
116
|
[:dom, :value, :serialize, :assign, :collection, :field, :kit]).to_set
|
|
134
117
|
return if base_methods.include?(method_name)
|
|
135
118
|
return if kit_class.method_defined?(method_name)
|
|
136
|
-
|
|
119
|
+
|
|
137
120
|
kit_class.define_method(method_name) do |*args, **kwargs, &block|
|
|
138
121
|
result = @field.send(method_name, *args, **kwargs, &block)
|
|
139
122
|
@form.render result
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module Superform
|
|
2
|
+
module Rails
|
|
3
|
+
module Choices
|
|
4
|
+
class Choice
|
|
5
|
+
attr_reader :value, :text, :index
|
|
6
|
+
|
|
7
|
+
def initialize(component:, field:, value:, text:, index:, type:)
|
|
8
|
+
@component = component
|
|
9
|
+
@field = field
|
|
10
|
+
@value = value
|
|
11
|
+
@text = text
|
|
12
|
+
@index = index
|
|
13
|
+
@type = type
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def input(**attrs)
|
|
17
|
+
@component.render build_input(**attrs)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def label(**attrs, &block)
|
|
21
|
+
label_text = @text
|
|
22
|
+
block ||= proc { label_text }
|
|
23
|
+
@component.render Components::Label.new(
|
|
24
|
+
@field, for: DOM.join(@field.dom.id, @index), **attrs, &block
|
|
25
|
+
)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def build_input(**attrs)
|
|
29
|
+
case @type
|
|
30
|
+
when :radio
|
|
31
|
+
Components::Radio.new(@field, value: @value, index: @index, **attrs)
|
|
32
|
+
when :checkbox
|
|
33
|
+
Components::Checkbox.new(@field, value: @value, index: @index, **attrs)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module Superform
|
|
2
|
+
module Rails
|
|
3
|
+
module Choices
|
|
4
|
+
# Maps collections of options into (value, text) pairs for form controls.
|
|
5
|
+
# Accepts arrays, hashes, single values, and ActiveRecord relations.
|
|
6
|
+
class Mapper
|
|
7
|
+
include Enumerable
|
|
8
|
+
|
|
9
|
+
def initialize(collection)
|
|
10
|
+
@collection = collection
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def each(&options)
|
|
14
|
+
@collection.each do |object|
|
|
15
|
+
case object
|
|
16
|
+
in ActiveRecord::Relation => relation
|
|
17
|
+
active_record_relation_options_enumerable(relation).each(&options)
|
|
18
|
+
in Hash => hash
|
|
19
|
+
hash.each { |id, value| options.call id, value }
|
|
20
|
+
in id, value
|
|
21
|
+
options.call id, value
|
|
22
|
+
in value
|
|
23
|
+
options.call value, value.to_s
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def active_record_relation_options_enumerable(relation)
|
|
29
|
+
Enumerator.new do |collection|
|
|
30
|
+
relation.each do |object|
|
|
31
|
+
attributes = object.attributes
|
|
32
|
+
id = attributes.delete(relation.primary_key)
|
|
33
|
+
value = attributes.values.join(" ")
|
|
34
|
+
collection << [ id, value ]
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -6,9 +6,16 @@ module Superform
|
|
|
6
6
|
|
|
7
7
|
delegate :dom, to: :field
|
|
8
8
|
|
|
9
|
-
def initialize(field, attributes:
|
|
9
|
+
def initialize(field, attributes: nil, **attributes_kwargs)
|
|
10
10
|
@field = field
|
|
11
|
-
|
|
11
|
+
if attributes
|
|
12
|
+
warn "[DEPRECATION] Passing `attributes:` keyword to #{self.class.name} is deprecated. " \
|
|
13
|
+
"Pass HTML attributes as keyword arguments directly instead: " \
|
|
14
|
+
"#{self.class.name}.new(field, **attributes)"
|
|
15
|
+
@attributes = attributes.merge(attributes_kwargs)
|
|
16
|
+
else
|
|
17
|
+
@attributes = attributes_kwargs
|
|
18
|
+
end
|
|
12
19
|
end
|
|
13
20
|
|
|
14
21
|
def field_attributes
|
|
@@ -2,18 +2,45 @@ module Superform
|
|
|
2
2
|
module Rails
|
|
3
3
|
module Components
|
|
4
4
|
class Checkbox < Field
|
|
5
|
+
def initialize(field, index: nil, **attributes)
|
|
6
|
+
super(field, **attributes)
|
|
7
|
+
@index = index
|
|
8
|
+
end
|
|
9
|
+
|
|
5
10
|
def view_template(&)
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
if boolean?
|
|
12
|
+
# Rails convention: hidden input ensures a value is sent even when unchecked
|
|
13
|
+
input(name: dom.name, type: :hidden, value: "0")
|
|
14
|
+
input(type: :checkbox, value: "1", **attributes)
|
|
15
|
+
elsif collection?
|
|
16
|
+
input(type: :checkbox, value: dom.value, **attributes)
|
|
17
|
+
else
|
|
18
|
+
input(type: :checkbox, **attributes)
|
|
19
|
+
end
|
|
11
20
|
end
|
|
12
21
|
|
|
13
22
|
def field_attributes
|
|
14
|
-
|
|
23
|
+
if boolean?
|
|
24
|
+
{ id: dom.id, name: dom.name, checked: field.value }
|
|
25
|
+
elsif collection?
|
|
26
|
+
{ id: dom.id, name: dom.name, checked: true }
|
|
27
|
+
else
|
|
28
|
+
{ id: DOM.join(dom.id, @index || @attributes[:value]), name: dom.array_name, checked: Array(field.value).include?(@attributes[:value]) }
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
# Inside a FieldCollection — the field is a child of another Field
|
|
35
|
+
def collection?
|
|
36
|
+
field.parent.is_a?(Superform::Field)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Scalar field with no explicit value — classic on/off toggle
|
|
40
|
+
def boolean?
|
|
41
|
+
!collection? && !field.value.is_a?(Array)
|
|
15
42
|
end
|
|
16
43
|
end
|
|
17
44
|
end
|
|
18
45
|
end
|
|
19
|
-
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module Superform
|
|
2
|
+
module Rails
|
|
3
|
+
module Components
|
|
4
|
+
class Checkboxes < Base
|
|
5
|
+
def initialize(field, options: [], **attributes)
|
|
6
|
+
super(field, **attributes)
|
|
7
|
+
@options = options
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def view_template(&block)
|
|
11
|
+
choices.each do |choice|
|
|
12
|
+
if block
|
|
13
|
+
yield choice
|
|
14
|
+
else
|
|
15
|
+
label(for: DOM.join(dom.id, choice.index)) do
|
|
16
|
+
render choice.build_input
|
|
17
|
+
whitespace
|
|
18
|
+
plain choice.text
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def choices
|
|
27
|
+
Choices::Mapper.new(@options).each_with_index.map do |(value, text), index|
|
|
28
|
+
Choices::Choice.new(component: self, field: @field, value:, text:, index:, type: :checkbox)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def field_attributes
|
|
33
|
+
{}
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module Superform
|
|
2
|
+
module Rails
|
|
3
|
+
module Components
|
|
4
|
+
class Datalist < Field
|
|
5
|
+
def initialize(field, options: [], **attributes)
|
|
6
|
+
super(field, **attributes)
|
|
7
|
+
@options = options
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def view_template(&block)
|
|
11
|
+
datalist_id = DOM.join(dom.id, "datalist")
|
|
12
|
+
input(list: datalist_id, **attributes)
|
|
13
|
+
datalist(id: datalist_id) do
|
|
14
|
+
if block
|
|
15
|
+
yield self
|
|
16
|
+
else
|
|
17
|
+
options(*@options)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def options(*collection)
|
|
23
|
+
Choices::Mapper.new(collection).each do |value, text|
|
|
24
|
+
if value == text
|
|
25
|
+
option(value: value)
|
|
26
|
+
else
|
|
27
|
+
option(value: value) { text }
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Superform
|
|
2
|
+
module Rails
|
|
3
|
+
module Components
|
|
4
|
+
class Radio < Field
|
|
5
|
+
def initialize(field, value:, index: value, **attributes)
|
|
6
|
+
super(field, **attributes)
|
|
7
|
+
@value = value
|
|
8
|
+
@index = index
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def view_template(&)
|
|
12
|
+
input(type: :radio, **attributes)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def field_attributes
|
|
16
|
+
{ id: DOM.join(dom.id, @index), name: dom.name, value: @value, checked: field.value == @value }
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module Superform
|
|
2
|
+
module Rails
|
|
3
|
+
module Components
|
|
4
|
+
class Radios < Base
|
|
5
|
+
def initialize(field, options: [], **attributes)
|
|
6
|
+
super(field, **attributes)
|
|
7
|
+
@options = options
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def view_template(&block)
|
|
11
|
+
choices.each do |choice|
|
|
12
|
+
if block
|
|
13
|
+
yield choice
|
|
14
|
+
else
|
|
15
|
+
label(for: DOM.join(dom.id, choice.index)) do
|
|
16
|
+
render choice.build_input
|
|
17
|
+
whitespace
|
|
18
|
+
plain choice.text
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def choices
|
|
27
|
+
Choices::Mapper.new(@options).each_with_index.map do |(value, text), index|
|
|
28
|
+
Choices::Choice.new(component: self, field: @field, value:, text:, index:, type: :radio)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def field_attributes
|
|
33
|
+
{}
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -2,22 +2,54 @@ module Superform
|
|
|
2
2
|
module Rails
|
|
3
3
|
module Components
|
|
4
4
|
class Select < Field
|
|
5
|
-
def initialize(
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
def initialize(
|
|
6
|
+
field,
|
|
7
|
+
options: [],
|
|
8
|
+
collection: nil,
|
|
9
|
+
multiple: false,
|
|
10
|
+
**attributes,
|
|
11
|
+
&
|
|
12
|
+
)
|
|
13
|
+
super(field, **attributes, &)
|
|
14
|
+
|
|
15
|
+
# Handle deprecated collection parameter
|
|
16
|
+
if collection && options.empty?
|
|
17
|
+
warn "[DEPRECATION] Superform::Rails::Components::Select: " \
|
|
18
|
+
"`collection:` keyword is deprecated and will be removed. " \
|
|
19
|
+
"Use positional arguments instead: field.select([1, 'A'], [2, 'B'])"
|
|
20
|
+
options = collection
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
@options = options
|
|
24
|
+
@multiple = multiple
|
|
8
25
|
end
|
|
9
26
|
|
|
10
|
-
def view_template(&
|
|
27
|
+
def view_template(&block)
|
|
28
|
+
# Hidden input ensures a value is sent even when all options are
|
|
29
|
+
# deselected in a multiple select
|
|
30
|
+
if @multiple
|
|
31
|
+
hidden_name = field.parent.is_a?(Superform::Field) ? dom.name : dom.array_name
|
|
32
|
+
input(type: "hidden", name: hidden_name, value: "")
|
|
33
|
+
end
|
|
34
|
+
|
|
11
35
|
if block_given?
|
|
12
|
-
select(**attributes, &
|
|
36
|
+
select(**attributes, &block)
|
|
13
37
|
else
|
|
14
|
-
select(**attributes)
|
|
38
|
+
select(**attributes) do
|
|
39
|
+
options(*@options)
|
|
40
|
+
end
|
|
15
41
|
end
|
|
16
42
|
end
|
|
17
43
|
|
|
18
44
|
def options(*collection)
|
|
45
|
+
# Handle both single values and arrays (for multiple selects)
|
|
46
|
+
selected_values = Array(field.value)
|
|
19
47
|
map_options(collection).each do |key, value|
|
|
20
|
-
|
|
48
|
+
if key.nil?
|
|
49
|
+
blank_option
|
|
50
|
+
else
|
|
51
|
+
option(selected: selected_values.include?(key), value: key) { value }
|
|
52
|
+
end
|
|
21
53
|
end
|
|
22
54
|
end
|
|
23
55
|
|
|
@@ -35,7 +67,19 @@ module Superform
|
|
|
35
67
|
|
|
36
68
|
protected
|
|
37
69
|
def map_options(collection)
|
|
38
|
-
|
|
70
|
+
Choices::Mapper.new(collection)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def field_attributes
|
|
74
|
+
attrs = super
|
|
75
|
+
if @multiple
|
|
76
|
+
# Only append [] if the field doesn't already have a Field parent
|
|
77
|
+
# (which would mean it's already in a collection and has [] notation)
|
|
78
|
+
name = field.parent.is_a?(Superform::Field) ? attrs[:name] : dom.array_name
|
|
79
|
+
attrs.merge(multiple: true, name: name)
|
|
80
|
+
else
|
|
81
|
+
attrs
|
|
82
|
+
end
|
|
39
83
|
end
|
|
40
84
|
end
|
|
41
85
|
end
|