simple_form 2.0.0 → 3.5.1
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.
Potentially problematic release.
This version of simple_form might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/CHANGELOG.md +97 -198
- data/MIT-LICENSE +1 -1
- data/README.md +572 -296
- data/lib/generators/simple_form/install_generator.rb +17 -7
- data/lib/generators/simple_form/templates/README +3 -4
- data/lib/generators/simple_form/templates/_form.html.erb +1 -0
- data/lib/generators/simple_form/templates/_form.html.haml +1 -0
- data/lib/generators/simple_form/templates/config/initializers/{simple_form.rb.tt → simple_form.rb} +57 -63
- data/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +155 -0
- data/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb +111 -0
- data/lib/generators/simple_form/templates/config/locales/simple_form.en.yml +14 -7
- data/lib/simple_form/action_view_extensions/builder.rb +5 -305
- data/lib/simple_form/action_view_extensions/form_helper.rb +18 -20
- data/lib/simple_form/components/errors.rb +30 -3
- data/lib/simple_form/components/hints.rb +10 -3
- data/lib/simple_form/components/html5.rb +17 -3
- data/lib/simple_form/components/label_input.rb +21 -2
- data/lib/simple_form/components/labels.rb +16 -11
- data/lib/simple_form/components/maxlength.rb +19 -12
- data/lib/simple_form/components/min_max.rb +4 -2
- data/lib/simple_form/components/minlength.rb +48 -0
- data/lib/simple_form/components/pattern.rb +5 -4
- data/lib/simple_form/components/placeholders.rb +3 -2
- data/lib/simple_form/components/readonly.rb +3 -2
- data/lib/simple_form/components.rb +15 -11
- data/lib/simple_form/error_notification.rb +4 -3
- data/lib/simple_form/form_builder.rb +283 -105
- data/lib/simple_form/helpers/autofocus.rb +1 -0
- data/lib/simple_form/helpers/disabled.rb +1 -0
- data/lib/simple_form/helpers/readonly.rb +1 -0
- data/lib/simple_form/helpers/required.rb +1 -0
- data/lib/simple_form/helpers/validators.rb +4 -3
- data/lib/simple_form/helpers.rb +7 -6
- data/lib/simple_form/i18n_cache.rb +1 -0
- data/lib/simple_form/inputs/base.rb +76 -23
- data/lib/simple_form/inputs/block_input.rb +3 -2
- data/lib/simple_form/inputs/boolean_input.rb +55 -16
- data/lib/simple_form/inputs/collection_check_boxes_input.rb +2 -1
- data/lib/simple_form/inputs/collection_input.rb +41 -18
- data/lib/simple_form/inputs/collection_radio_buttons_input.rb +11 -19
- data/lib/simple_form/inputs/collection_select_input.rb +5 -2
- data/lib/simple_form/inputs/date_time_input.rb +23 -12
- data/lib/simple_form/inputs/file_input.rb +5 -2
- data/lib/simple_form/inputs/grouped_collection_select_input.rb +16 -3
- data/lib/simple_form/inputs/hidden_input.rb +5 -2
- data/lib/simple_form/inputs/numeric_input.rb +4 -8
- data/lib/simple_form/inputs/password_input.rb +6 -4
- data/lib/simple_form/inputs/priority_input.rb +5 -2
- data/lib/simple_form/inputs/range_input.rb +2 -1
- data/lib/simple_form/inputs/string_input.rb +6 -4
- data/lib/simple_form/inputs/text_input.rb +6 -3
- data/lib/simple_form/inputs.rb +20 -17
- data/lib/simple_form/map_type.rb +1 -0
- data/lib/simple_form/railtie.rb +15 -0
- data/lib/simple_form/tags.rb +69 -0
- data/lib/simple_form/version.rb +2 -1
- data/lib/simple_form/wrappers/builder.rb +12 -35
- data/lib/simple_form/wrappers/leaf.rb +29 -0
- data/lib/simple_form/wrappers/many.rb +12 -7
- data/lib/simple_form/wrappers/root.rb +7 -4
- data/lib/simple_form/wrappers/single.rb +12 -3
- data/lib/simple_form/wrappers.rb +3 -1
- data/lib/simple_form.rb +118 -63
- data/test/action_view_extensions/builder_test.rb +230 -164
- data/test/action_view_extensions/form_helper_test.rb +107 -39
- data/test/components/label_test.rb +105 -87
- data/test/form_builder/association_test.rb +131 -62
- data/test/form_builder/button_test.rb +15 -14
- data/test/form_builder/error_notification_test.rb +11 -10
- data/test/form_builder/error_test.rb +188 -34
- data/test/form_builder/general_test.rb +247 -102
- data/test/form_builder/hint_test.rb +59 -32
- data/test/form_builder/input_field_test.rb +138 -25
- data/test/form_builder/label_test.rb +84 -13
- data/test/form_builder/wrapper_test.rb +236 -33
- data/test/generators/simple_form_generator_test.rb +15 -4
- data/test/inputs/boolean_input_test.rb +147 -13
- data/test/inputs/collection_check_boxes_input_test.rb +166 -71
- data/test/inputs/collection_radio_buttons_input_test.rb +229 -113
- data/test/inputs/collection_select_input_test.rb +222 -85
- data/test/inputs/datetime_input_test.rb +134 -47
- data/test/inputs/disabled_test.rb +62 -21
- data/test/inputs/discovery_test.rb +70 -10
- data/test/inputs/file_input_test.rb +4 -3
- data/test/inputs/general_test.rb +90 -26
- data/test/inputs/grouped_collection_select_input_test.rb +88 -23
- data/test/inputs/hidden_input_test.rb +7 -5
- data/test/inputs/numeric_input_test.rb +56 -46
- data/test/inputs/priority_input_test.rb +31 -16
- data/test/inputs/readonly_test.rb +68 -27
- data/test/inputs/required_test.rb +63 -18
- data/test/inputs/string_input_test.rb +76 -51
- data/test/inputs/text_input_test.rb +21 -8
- data/test/simple_form_test.rb +9 -0
- data/test/support/discovery_inputs.rb +39 -2
- data/test/support/misc_helpers.rb +176 -20
- data/test/support/mock_controller.rb +13 -7
- data/test/support/models.rb +187 -71
- data/test/test_helper.rb +38 -39
- metadata +53 -39
- data/lib/simple_form/core_ext/hash.rb +0 -16
- data/test/support/mock_response.rb +0 -14
|
@@ -1,11 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module SimpleForm
|
|
2
3
|
module Inputs
|
|
3
4
|
class GroupedCollectionSelectInput < CollectionInput
|
|
4
|
-
def input
|
|
5
|
+
def input(wrapper_options = nil)
|
|
5
6
|
label_method, value_method = detect_collection_methods
|
|
7
|
+
|
|
8
|
+
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
|
|
9
|
+
|
|
6
10
|
@builder.grouped_collection_select(attribute_name, grouped_collection,
|
|
7
11
|
group_method, group_label_method, value_method, label_method,
|
|
8
|
-
input_options,
|
|
12
|
+
input_options, merged_input_options)
|
|
9
13
|
end
|
|
10
14
|
|
|
11
15
|
private
|
|
@@ -19,7 +23,7 @@ module SimpleForm
|
|
|
19
23
|
|
|
20
24
|
# Sample collection
|
|
21
25
|
def collection
|
|
22
|
-
@collection ||= grouped_collection.
|
|
26
|
+
@collection ||= grouped_collection.map { |collection| collection.try(:send, group_method) }.detect(&:present?) || []
|
|
23
27
|
end
|
|
24
28
|
|
|
25
29
|
def group_method
|
|
@@ -36,6 +40,15 @@ module SimpleForm
|
|
|
36
40
|
|
|
37
41
|
label
|
|
38
42
|
end
|
|
43
|
+
|
|
44
|
+
def detect_method_from_class(collection_classes)
|
|
45
|
+
return {} if collection_classes.empty?
|
|
46
|
+
|
|
47
|
+
sample = collection_classes.first
|
|
48
|
+
|
|
49
|
+
{ label: SimpleForm.collection_label_methods.find { |m| sample.instance_methods.include?(m) },
|
|
50
|
+
value: SimpleForm.collection_value_methods.find { |m| sample.instance_methods.include?(m) } }
|
|
51
|
+
end
|
|
39
52
|
end
|
|
40
53
|
end
|
|
41
54
|
end
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module SimpleForm
|
|
2
3
|
module Inputs
|
|
3
4
|
class HiddenInput < Base
|
|
4
5
|
disable :label, :errors, :hint, :required
|
|
5
6
|
|
|
6
|
-
def input
|
|
7
|
-
|
|
7
|
+
def input(wrapper_options = nil)
|
|
8
|
+
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
|
|
9
|
+
|
|
10
|
+
@builder.hidden_field(attribute_name, merged_input_options)
|
|
8
11
|
end
|
|
9
12
|
|
|
10
13
|
private
|
|
@@ -1,23 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module SimpleForm
|
|
2
3
|
module Inputs
|
|
3
4
|
class NumericInput < Base
|
|
4
5
|
enable :placeholder, :min_max
|
|
5
6
|
|
|
6
|
-
def input
|
|
7
|
-
add_size!
|
|
7
|
+
def input(wrapper_options = nil)
|
|
8
8
|
input_html_classes.unshift("numeric")
|
|
9
9
|
if html5?
|
|
10
10
|
input_html_options[:type] ||= "number"
|
|
11
11
|
input_html_options[:step] ||= integer? ? 1 : "any"
|
|
12
12
|
end
|
|
13
|
-
@builder.text_field(attribute_name, input_html_options)
|
|
14
|
-
end
|
|
15
13
|
|
|
16
|
-
|
|
14
|
+
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
|
|
17
15
|
|
|
18
|
-
|
|
19
|
-
def add_size!
|
|
20
|
-
input_html_options[:size] ||= nil
|
|
16
|
+
@builder.text_field(attribute_name, merged_input_options)
|
|
21
17
|
end
|
|
22
18
|
end
|
|
23
19
|
end
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module SimpleForm
|
|
2
3
|
module Inputs
|
|
3
4
|
class PasswordInput < Base
|
|
4
|
-
enable :placeholder, :maxlength
|
|
5
|
+
enable :placeholder, :maxlength, :minlength
|
|
5
6
|
|
|
6
|
-
def input
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
def input(wrapper_options = nil)
|
|
8
|
+
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
|
|
9
|
+
|
|
10
|
+
@builder.password_field(attribute_name, merged_input_options)
|
|
9
11
|
end
|
|
10
12
|
end
|
|
11
13
|
end
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module SimpleForm
|
|
2
3
|
module Inputs
|
|
3
4
|
class PriorityInput < CollectionSelectInput
|
|
4
|
-
def input
|
|
5
|
+
def input(wrapper_options = nil)
|
|
6
|
+
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
|
|
7
|
+
|
|
5
8
|
@builder.send(:"#{input_type}_select", attribute_name, input_priority,
|
|
6
|
-
input_options,
|
|
9
|
+
input_options, merged_input_options)
|
|
7
10
|
end
|
|
8
11
|
|
|
9
12
|
def input_priority
|
|
@@ -1,16 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module SimpleForm
|
|
2
3
|
module Inputs
|
|
3
4
|
class StringInput < Base
|
|
4
|
-
enable :placeholder, :maxlength, :pattern
|
|
5
|
+
enable :placeholder, :maxlength, :minlength, :pattern
|
|
5
6
|
|
|
6
|
-
def input
|
|
7
|
+
def input(wrapper_options = nil)
|
|
7
8
|
unless string?
|
|
8
9
|
input_html_classes.unshift("string")
|
|
9
10
|
input_html_options[:type] ||= input_type if html5?
|
|
10
11
|
end
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
|
|
14
|
+
|
|
15
|
+
@builder.text_field(attribute_name, merged_input_options)
|
|
14
16
|
end
|
|
15
17
|
|
|
16
18
|
private
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module SimpleForm
|
|
2
3
|
module Inputs
|
|
3
4
|
class TextInput < Base
|
|
4
|
-
enable :placeholder, :maxlength
|
|
5
|
+
enable :placeholder, :maxlength, :minlength
|
|
5
6
|
|
|
6
|
-
def input
|
|
7
|
-
|
|
7
|
+
def input(wrapper_options = nil)
|
|
8
|
+
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
|
|
9
|
+
|
|
10
|
+
@builder.text_area(attribute_name, merged_input_options)
|
|
8
11
|
end
|
|
9
12
|
end
|
|
10
13
|
end
|
data/lib/simple_form/inputs.rb
CHANGED
|
@@ -1,21 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module SimpleForm
|
|
2
3
|
module Inputs
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
autoload :
|
|
6
|
-
autoload :
|
|
7
|
-
autoload :
|
|
8
|
-
autoload :
|
|
9
|
-
autoload :
|
|
10
|
-
autoload :
|
|
11
|
-
autoload :
|
|
12
|
-
autoload :
|
|
13
|
-
autoload :
|
|
14
|
-
autoload :
|
|
15
|
-
autoload :
|
|
16
|
-
autoload :
|
|
17
|
-
autoload :
|
|
18
|
-
autoload :
|
|
19
|
-
autoload :
|
|
4
|
+
extend ActiveSupport::Autoload
|
|
5
|
+
|
|
6
|
+
autoload :Base
|
|
7
|
+
autoload :BlockInput
|
|
8
|
+
autoload :BooleanInput
|
|
9
|
+
autoload :CollectionCheckBoxesInput
|
|
10
|
+
autoload :CollectionInput
|
|
11
|
+
autoload :CollectionRadioButtonsInput
|
|
12
|
+
autoload :CollectionSelectInput
|
|
13
|
+
autoload :DateTimeInput
|
|
14
|
+
autoload :FileInput
|
|
15
|
+
autoload :GroupedCollectionSelectInput
|
|
16
|
+
autoload :HiddenInput
|
|
17
|
+
autoload :NumericInput
|
|
18
|
+
autoload :PasswordInput
|
|
19
|
+
autoload :PriorityInput
|
|
20
|
+
autoload :RangeInput
|
|
21
|
+
autoload :StringInput
|
|
22
|
+
autoload :TextInput
|
|
20
23
|
end
|
|
21
24
|
end
|
data/lib/simple_form/map_type.rb
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'rails/railtie'
|
|
3
|
+
|
|
4
|
+
module SimpleForm
|
|
5
|
+
class Railtie < Rails::Railtie
|
|
6
|
+
config.eager_load_namespaces << SimpleForm
|
|
7
|
+
|
|
8
|
+
config.after_initialize do
|
|
9
|
+
unless SimpleForm.configured?
|
|
10
|
+
warn '[Simple Form] Simple Form is not configured in the application and will use the default values.' +
|
|
11
|
+
' Use `rails generate simple_form:install` to generate the Simple Form configuration.'
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module SimpleForm
|
|
3
|
+
module Tags
|
|
4
|
+
module CollectionExtensions
|
|
5
|
+
private
|
|
6
|
+
|
|
7
|
+
def render_collection
|
|
8
|
+
item_wrapper_tag = @options.fetch(:item_wrapper_tag, :span)
|
|
9
|
+
item_wrapper_class = @options[:item_wrapper_class]
|
|
10
|
+
|
|
11
|
+
@collection.map do |item|
|
|
12
|
+
value = value_for_collection(item, @value_method)
|
|
13
|
+
text = value_for_collection(item, @text_method)
|
|
14
|
+
default_html_options = default_html_options_for_collection(item, value)
|
|
15
|
+
additional_html_options = option_html_attributes(item)
|
|
16
|
+
|
|
17
|
+
rendered_item = yield item, value, text, default_html_options.merge(additional_html_options)
|
|
18
|
+
|
|
19
|
+
if @options.fetch(:boolean_style, SimpleForm.boolean_style) == :nested
|
|
20
|
+
label_options = default_html_options.slice(:index, :namespace)
|
|
21
|
+
label_options['class'] = @options[:item_label_class]
|
|
22
|
+
rendered_item = @template_object.label(@object_name, sanitize_attribute_name(value), rendered_item, label_options)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
item_wrapper_tag ? @template_object.content_tag(item_wrapper_tag, rendered_item, class: item_wrapper_class) : rendered_item
|
|
26
|
+
end.join.html_safe
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def wrap_rendered_collection(collection)
|
|
30
|
+
wrapper_tag = @options[:collection_wrapper_tag]
|
|
31
|
+
|
|
32
|
+
if wrapper_tag
|
|
33
|
+
wrapper_class = @options[:collection_wrapper_class]
|
|
34
|
+
@template_object.content_tag(wrapper_tag, collection, class: wrapper_class)
|
|
35
|
+
else
|
|
36
|
+
collection
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
class CollectionRadioButtons < ActionView::Helpers::Tags::CollectionRadioButtons
|
|
42
|
+
include CollectionExtensions
|
|
43
|
+
|
|
44
|
+
def render
|
|
45
|
+
wrap_rendered_collection(super)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
def render_component(builder)
|
|
51
|
+
builder.radio_button + builder.label(class: "collection_radio_buttons")
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
class CollectionCheckBoxes < ActionView::Helpers::Tags::CollectionCheckBoxes
|
|
56
|
+
include CollectionExtensions
|
|
57
|
+
|
|
58
|
+
def render
|
|
59
|
+
wrap_rendered_collection(super)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def render_component(builder)
|
|
65
|
+
builder.check_box + builder.label(class: "collection_check_boxes")
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
data/lib/simple_form/version.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module SimpleForm
|
|
2
3
|
module Wrappers
|
|
3
4
|
# Provides the builder syntax for components. The builder provides
|
|
@@ -12,18 +13,18 @@ module SimpleForm
|
|
|
12
13
|
# b.optional :placeholder
|
|
13
14
|
#
|
|
14
15
|
# # Use a component with specific wrapper options
|
|
15
|
-
# b.use :error, :
|
|
16
|
+
# b.use :error, wrap_with: { tag: "span", class: "error" }
|
|
16
17
|
#
|
|
17
18
|
# # Use a set of components by wrapping them in a tag+class.
|
|
18
|
-
# b.wrapper :
|
|
19
|
+
# b.wrapper tag: "div", class: "another" do |ba|
|
|
19
20
|
# ba.use :label
|
|
20
21
|
# ba.use :input
|
|
21
22
|
# end
|
|
22
23
|
#
|
|
23
24
|
# # Use a set of components by wrapping them in a tag+class.
|
|
24
25
|
# # This wrapper is identified by :label_input, which means it can
|
|
25
|
-
# # be turned off on demand with `f.input :name, :
|
|
26
|
-
# b.wrapper :label_input, :
|
|
26
|
+
# # be turned off on demand with `f.input :name, label_input: false`
|
|
27
|
+
# b.wrapper :label_input, tag: "div", class: "another" do |ba|
|
|
27
28
|
# ba.use :label
|
|
28
29
|
# ba.use :input
|
|
29
30
|
# end
|
|
@@ -32,7 +33,7 @@ module SimpleForm
|
|
|
32
33
|
# The builder also accepts default options at the root level. This is usually
|
|
33
34
|
# used if you want a component to be disabled by default:
|
|
34
35
|
#
|
|
35
|
-
# config.wrappers :
|
|
36
|
+
# config.wrappers hint: false do |b|
|
|
36
37
|
# b.use :hint
|
|
37
38
|
# b.use :label_input
|
|
38
39
|
# end
|
|
@@ -45,44 +46,20 @@ module SimpleForm
|
|
|
45
46
|
@components = []
|
|
46
47
|
end
|
|
47
48
|
|
|
48
|
-
def use(name, options=
|
|
49
|
-
if block_given?
|
|
50
|
-
ActiveSupport::Deprecation.warn "Passing a block to use is deprecated. " \
|
|
51
|
-
"Please use wrapper instead of use."
|
|
52
|
-
return wrapper(name, options, &block)
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
if options && options.keys != [:wrap_with]
|
|
56
|
-
ActiveSupport::Deprecation.warn "Passing :tag, :class and others to use is deprecated. " \
|
|
57
|
-
"Please invoke b.use #{name.inspect}, :wrap_with => #{options.inspect} instead."
|
|
58
|
-
options = { :wrap_with => options }
|
|
59
|
-
end
|
|
60
|
-
|
|
49
|
+
def use(name, options = {})
|
|
61
50
|
if options && wrapper = options[:wrap_with]
|
|
62
|
-
@components << Single.new(name, wrapper)
|
|
51
|
+
@components << Single.new(name, wrapper, options.except(:wrap_with))
|
|
63
52
|
else
|
|
64
|
-
@components << name
|
|
53
|
+
@components << Leaf.new(name, options)
|
|
65
54
|
end
|
|
66
55
|
end
|
|
67
56
|
|
|
68
|
-
def optional(name, options=
|
|
69
|
-
if block_given?
|
|
70
|
-
ActiveSupport::Deprecation.warn "Passing a block to optional is deprecated. " \
|
|
71
|
-
"Please use wrapper instead of optional."
|
|
72
|
-
return wrapper(name, options, &block)
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
if options && options.keys != [:wrap_with]
|
|
76
|
-
ActiveSupport::Deprecation.warn "Passing :tag, :class and others to optional is deprecated. " \
|
|
77
|
-
"Please invoke b.optional #{name.inspect}, :wrap_with => #{options.inspect} instead."
|
|
78
|
-
options = { :wrap_with => options }
|
|
79
|
-
end
|
|
80
|
-
|
|
57
|
+
def optional(name, options = {}, &block)
|
|
81
58
|
@options[name] = false
|
|
82
|
-
use(name, options
|
|
59
|
+
use(name, options)
|
|
83
60
|
end
|
|
84
61
|
|
|
85
|
-
def wrapper(name, options=nil)
|
|
62
|
+
def wrapper(name, options = nil)
|
|
86
63
|
if block_given?
|
|
87
64
|
name, options = nil, name if name.is_a?(Hash)
|
|
88
65
|
builder = self.class.new(@options)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module SimpleForm
|
|
3
|
+
module Wrappers
|
|
4
|
+
class Leaf
|
|
5
|
+
attr_reader :namespace
|
|
6
|
+
|
|
7
|
+
def initialize(namespace, options = {})
|
|
8
|
+
@namespace = namespace
|
|
9
|
+
@options = options
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def render(input)
|
|
13
|
+
method = input.method(@namespace)
|
|
14
|
+
|
|
15
|
+
if method.arity.zero?
|
|
16
|
+
ActiveSupport::Deprecation.warn(SimpleForm::CUSTOM_INPUT_DEPRECATION_WARN % { name: @namespace })
|
|
17
|
+
|
|
18
|
+
method.call
|
|
19
|
+
else
|
|
20
|
+
method.call(@options)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def find(name)
|
|
25
|
+
self if @namespace == name
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module SimpleForm
|
|
2
3
|
module Wrappers
|
|
3
4
|
# A wrapper is an object that holds several components and render them.
|
|
4
|
-
# A component may
|
|
5
|
+
# A component may be any object that responds to `render`.
|
|
5
6
|
# This API allows inputs/components to be easily wrapped, removing the
|
|
6
7
|
# need to modify the code only to wrap input in an extra tag.
|
|
7
8
|
#
|
|
@@ -10,14 +11,13 @@ module SimpleForm
|
|
|
10
11
|
# on demand on input generation.
|
|
11
12
|
class Many
|
|
12
13
|
attr_reader :namespace, :defaults, :components
|
|
13
|
-
alias :to_sym :namespace
|
|
14
14
|
|
|
15
|
-
def initialize(namespace, components, defaults={})
|
|
15
|
+
def initialize(namespace, components, defaults = {})
|
|
16
16
|
@namespace = namespace
|
|
17
17
|
@components = components
|
|
18
18
|
@defaults = defaults
|
|
19
19
|
@defaults[:tag] = :div unless @defaults.key?(:tag)
|
|
20
|
-
@defaults[:class] = Array
|
|
20
|
+
@defaults[:class] = Array(@defaults[:class])
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def render(input)
|
|
@@ -25,8 +25,8 @@ module SimpleForm
|
|
|
25
25
|
options = input.options
|
|
26
26
|
|
|
27
27
|
components.each do |component|
|
|
28
|
-
next if options[component] == false
|
|
29
|
-
rendered = component.
|
|
28
|
+
next if options[component.namespace] == false
|
|
29
|
+
rendered = component.render(input)
|
|
30
30
|
content.safe_concat rendered.to_s if rendered
|
|
31
31
|
end
|
|
32
32
|
|
|
@@ -51,16 +51,21 @@ module SimpleForm
|
|
|
51
51
|
|
|
52
52
|
def wrap(input, options, content)
|
|
53
53
|
return content if options[namespace] == false
|
|
54
|
+
return if defaults[:unless_blank] && content.empty?
|
|
54
55
|
|
|
55
56
|
tag = (namespace && options[:"#{namespace}_tag"]) || @defaults[:tag]
|
|
56
57
|
return content unless tag
|
|
57
58
|
|
|
58
59
|
klass = html_classes(input, options)
|
|
59
|
-
opts = options
|
|
60
|
+
opts = html_options(options)
|
|
60
61
|
opts[:class] = (klass << opts[:class]).join(' ').strip unless klass.empty?
|
|
61
62
|
input.template.content_tag(tag, content, opts)
|
|
62
63
|
end
|
|
63
64
|
|
|
65
|
+
def html_options(options)
|
|
66
|
+
(@defaults[:html] || {}).merge(options[:"#{namespace}_html"] || {})
|
|
67
|
+
end
|
|
68
|
+
|
|
64
69
|
def html_classes(input, options)
|
|
65
70
|
@defaults[:class].dup
|
|
66
71
|
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module SimpleForm
|
|
2
3
|
module Wrappers
|
|
3
4
|
# `Root` is the root wrapper for all components. It is special cased to
|
|
@@ -17,17 +18,19 @@ module SimpleForm
|
|
|
17
18
|
|
|
18
19
|
# Provide a fallback if name cannot be found.
|
|
19
20
|
def find(name)
|
|
20
|
-
super || SimpleForm::Wrappers::Many.new(name, [name])
|
|
21
|
+
super || SimpleForm::Wrappers::Many.new(name, [Leaf.new(name)])
|
|
21
22
|
end
|
|
22
23
|
|
|
23
24
|
private
|
|
24
25
|
|
|
25
26
|
def html_classes(input, options)
|
|
26
|
-
css = options[:wrapper_class] ? Array
|
|
27
|
-
css += SimpleForm.additional_classes_for(:wrapper)
|
|
27
|
+
css = options[:wrapper_class] ? Array(options[:wrapper_class]) : @defaults[:class]
|
|
28
|
+
css += SimpleForm.additional_classes_for(:wrapper) do
|
|
29
|
+
input.additional_classes + [input.input_class]
|
|
30
|
+
end
|
|
28
31
|
css << (options[:wrapper_error_class] || @defaults[:error_class]) if input.has_errors?
|
|
29
32
|
css << (options[:wrapper_hint_class] || @defaults[:hint_class]) if input.has_hint?
|
|
30
|
-
css
|
|
33
|
+
css.compact
|
|
31
34
|
end
|
|
32
35
|
end
|
|
33
36
|
end
|
|
@@ -1,18 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module SimpleForm
|
|
2
3
|
module Wrappers
|
|
3
4
|
# `Single` is an optimization for a wrapper that has only one component.
|
|
4
5
|
class Single < Many
|
|
5
|
-
def initialize(name, options={})
|
|
6
|
-
|
|
6
|
+
def initialize(name, wrapper_options = {}, options = {})
|
|
7
|
+
@component = Leaf.new(name, options)
|
|
8
|
+
|
|
9
|
+
super(name, [@component], wrapper_options)
|
|
7
10
|
end
|
|
8
11
|
|
|
9
12
|
def render(input)
|
|
10
13
|
options = input.options
|
|
11
14
|
if options[namespace] != false
|
|
12
|
-
content =
|
|
15
|
+
content = @component.render(input)
|
|
13
16
|
wrap(input, options, content) if content
|
|
14
17
|
end
|
|
15
18
|
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def html_options(options)
|
|
23
|
+
%i[label input].include?(namespace) ? {} : super
|
|
24
|
+
end
|
|
16
25
|
end
|
|
17
26
|
end
|
|
18
27
|
end
|
data/lib/simple_form/wrappers.rb
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module SimpleForm
|
|
2
3
|
module Wrappers
|
|
3
4
|
autoload :Builder, 'simple_form/wrappers/builder'
|
|
4
5
|
autoload :Many, 'simple_form/wrappers/many'
|
|
5
6
|
autoload :Root, 'simple_form/wrappers/root'
|
|
6
7
|
autoload :Single, 'simple_form/wrappers/single'
|
|
8
|
+
autoload :Leaf, 'simple_form/wrappers/leaf'
|
|
7
9
|
end
|
|
8
|
-
end
|
|
10
|
+
end
|