view_component-form 0.1.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 +7 -0
- data/CHANGELOG.md +16 -0
- data/LICENSE.txt +21 -0
- data/README.md +170 -0
- data/app/components/view_component/form/base_component.rb +53 -0
- data/app/components/view_component/form/button_component.rb +19 -0
- data/app/components/view_component/form/check_box_component.rb +27 -0
- data/app/components/view_component/form/collection_check_boxes_component.rb +50 -0
- data/app/components/view_component/form/collection_radio_buttons_component.rb +50 -0
- data/app/components/view_component/form/collection_select_component.rb +49 -0
- data/app/components/view_component/form/color_field_component.rb +9 -0
- data/app/components/view_component/form/date_field_component.rb +9 -0
- data/app/components/view_component/form/date_select_component.rb +34 -0
- data/app/components/view_component/form/datetime_field_component.rb +9 -0
- data/app/components/view_component/form/datetime_local_field_component.rb +9 -0
- data/app/components/view_component/form/datetime_select_component.rb +34 -0
- data/app/components/view_component/form/email_field_component.rb +9 -0
- data/app/components/view_component/form/field_component.rb +65 -0
- data/app/components/view_component/form/file_field_component.rb +9 -0
- data/app/components/view_component/form/grouped_collection_select_component.rb +57 -0
- data/app/components/view_component/form/label_component.rb +42 -0
- data/app/components/view_component/form/month_field_component.rb +9 -0
- data/app/components/view_component/form/number_field_component.rb +9 -0
- data/app/components/view_component/form/password_field_component.rb +9 -0
- data/app/components/view_component/form/radio_button_component.rb +27 -0
- data/app/components/view_component/form/range_field_component.rb +9 -0
- data/app/components/view_component/form/rich_text_area_component.rb +9 -0
- data/app/components/view_component/form/search_field_component.rb +9 -0
- data/app/components/view_component/form/select_component.rb +37 -0
- data/app/components/view_component/form/submit_component.rb +19 -0
- data/app/components/view_component/form/telephone_field_component.rb +9 -0
- data/app/components/view_component/form/text_area_component.rb +9 -0
- data/app/components/view_component/form/text_field_component.rb +9 -0
- data/app/components/view_component/form/time_field_component.rb +9 -0
- data/app/components/view_component/form/time_select_component.rb +34 -0
- data/app/components/view_component/form/time_zone_select_component.rb +36 -0
- data/app/components/view_component/form/url_field_component.rb +9 -0
- data/app/components/view_component/form/week_field_component.rb +9 -0
- data/lib/generators/vcf/builder/builder_generator.rb +32 -0
- data/lib/generators/vcf/builder/templates/builder.rb.erb +4 -0
- data/lib/view_component/form/builder.rb +212 -0
- data/lib/view_component/form/class_names_helper.rb +37 -0
- data/lib/view_component/form/engine.rb +15 -0
- data/lib/view_component/form/test_helpers.rb +29 -0
- data/lib/view_component/form/version.rb +7 -0
- data/lib/view_component/form.rb +5 -0
- metadata +152 -0
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponent
|
4
|
+
module Form
|
5
|
+
class DateSelectComponent < FieldComponent
|
6
|
+
attr_reader :html_options
|
7
|
+
|
8
|
+
def initialize(form, object_name, method_name, options = {}, html_options = {})
|
9
|
+
@html_options = html_options
|
10
|
+
|
11
|
+
super(form, object_name, method_name, options)
|
12
|
+
|
13
|
+
set_html_options!
|
14
|
+
end
|
15
|
+
|
16
|
+
def call
|
17
|
+
ActionView::Helpers::Tags::DateSelect.new(
|
18
|
+
object_name,
|
19
|
+
method_name,
|
20
|
+
@view_context,
|
21
|
+
options,
|
22
|
+
html_options
|
23
|
+
).render
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
def set_html_options!
|
29
|
+
@html_options[:class] = class_names(html_options[:class], html_class)
|
30
|
+
@html_options.delete(:class) if @html_options[:class].blank?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponent
|
4
|
+
module Form
|
5
|
+
class DatetimeSelectComponent < FieldComponent
|
6
|
+
attr_reader :html_options
|
7
|
+
|
8
|
+
def initialize(form, object_name, method_name, options = {}, html_options = {})
|
9
|
+
@html_options = html_options
|
10
|
+
|
11
|
+
super(form, object_name, method_name, options)
|
12
|
+
|
13
|
+
set_html_options!
|
14
|
+
end
|
15
|
+
|
16
|
+
def call
|
17
|
+
ActionView::Helpers::Tags::DatetimeSelect.new(
|
18
|
+
object_name,
|
19
|
+
method_name,
|
20
|
+
@view_context,
|
21
|
+
options,
|
22
|
+
html_options
|
23
|
+
).render
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
def set_html_options!
|
29
|
+
@html_options[:class] = class_names(html_options[:class], html_class)
|
30
|
+
@html_options.delete(:class) if @html_options[:class].blank?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponent
|
4
|
+
module Form
|
5
|
+
class FieldComponent < BaseComponent
|
6
|
+
class << self
|
7
|
+
attr_accessor :tag_klass
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :method_name
|
11
|
+
|
12
|
+
def initialize(form, object_name, method_name, options = {})
|
13
|
+
# See: https://github.com/rails/rails/blob/83217025a171593547d1268651b446d3533e2019/actionview/lib/action_view/helpers/tags/base.rb#L13
|
14
|
+
@method_name = method_name.to_s.dup
|
15
|
+
|
16
|
+
super(form, object_name, options)
|
17
|
+
end
|
18
|
+
|
19
|
+
def call
|
20
|
+
raise "`self.tag_klass' should be defined in #{self.class.name}" unless self.class.tag_klass
|
21
|
+
|
22
|
+
self.class.tag_klass.new(object_name, method_name, @view_context, options).render
|
23
|
+
end
|
24
|
+
|
25
|
+
def method_errors
|
26
|
+
return [] unless method_errors?
|
27
|
+
|
28
|
+
@method_errors ||= object_errors.to_hash
|
29
|
+
.fetch_values(*object_method_names) { nil }
|
30
|
+
.flatten.compact
|
31
|
+
.map(&:upcase_first)
|
32
|
+
end
|
33
|
+
|
34
|
+
def method_errors?
|
35
|
+
(object_errors.keys & object_method_names).any?
|
36
|
+
end
|
37
|
+
|
38
|
+
def value
|
39
|
+
object.public_send(method_name)
|
40
|
+
end
|
41
|
+
|
42
|
+
def object_method_names
|
43
|
+
@object_method_names ||= begin
|
44
|
+
object_method_names = [method_name]
|
45
|
+
if method_name.end_with?("_id") && object.respond_to?(singular_association_method_name)
|
46
|
+
object_method_names << singular_association_method_name
|
47
|
+
elsif method_name.end_with?("_ids") && object.respond_to?(collection_association_method_name)
|
48
|
+
object_method_names << collection_association_method_name
|
49
|
+
end
|
50
|
+
object_method_names
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def singular_association_method_name
|
57
|
+
@singular_association_method_name ||= method_name.to_s.sub(/_id$/, "").to_sym
|
58
|
+
end
|
59
|
+
|
60
|
+
def collection_association_method_name
|
61
|
+
@collection_association_method_name ||= method_name.to_s.sub(/_ids$/, "").pluralize.to_sym
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponent
|
4
|
+
module Form
|
5
|
+
class GroupedCollectionSelectComponent < FieldComponent
|
6
|
+
attr_reader :collection, :group_method,
|
7
|
+
:group_label_method, :option_key_method, :option_value_method,
|
8
|
+
:html_options
|
9
|
+
|
10
|
+
def initialize( # rubocop:disable Metrics/ParameterLists
|
11
|
+
form,
|
12
|
+
object_name,
|
13
|
+
method_name,
|
14
|
+
collection,
|
15
|
+
group_method,
|
16
|
+
group_label_method,
|
17
|
+
option_key_method,
|
18
|
+
option_value_method,
|
19
|
+
options = {},
|
20
|
+
html_options = {}
|
21
|
+
)
|
22
|
+
@collection = collection
|
23
|
+
@group_method = group_method
|
24
|
+
@group_label_method = group_label_method
|
25
|
+
@option_key_method = option_key_method
|
26
|
+
@option_value_method = option_value_method
|
27
|
+
@html_options = html_options
|
28
|
+
|
29
|
+
super(form, object_name, method_name, options)
|
30
|
+
|
31
|
+
set_html_options!
|
32
|
+
end
|
33
|
+
|
34
|
+
def call # rubocop:disable Metrics/MethodLength
|
35
|
+
ActionView::Helpers::Tags::GroupedCollectionSelect.new(
|
36
|
+
object_name,
|
37
|
+
method_name,
|
38
|
+
@view_context,
|
39
|
+
collection,
|
40
|
+
group_method,
|
41
|
+
group_label_method,
|
42
|
+
option_key_method,
|
43
|
+
option_value_method,
|
44
|
+
options,
|
45
|
+
html_options
|
46
|
+
).render
|
47
|
+
end
|
48
|
+
|
49
|
+
protected
|
50
|
+
|
51
|
+
def set_html_options!
|
52
|
+
@html_options[:class] = class_names(html_options[:class], html_class)
|
53
|
+
@html_options.delete(:class) if @html_options[:class].blank?
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponent
|
4
|
+
module Form
|
5
|
+
class LabelComponent < FieldComponent
|
6
|
+
attr_reader :attribute_content
|
7
|
+
|
8
|
+
def initialize(form, object_name, method_name, content_or_options = nil, options = nil)
|
9
|
+
options ||= {}
|
10
|
+
|
11
|
+
content_is_options = content_or_options.is_a?(Hash)
|
12
|
+
if content_is_options
|
13
|
+
options.merge! content_or_options
|
14
|
+
@attribute_content = nil
|
15
|
+
else
|
16
|
+
@attribute_content = content_or_options
|
17
|
+
end
|
18
|
+
|
19
|
+
super(form, object_name, method_name, options)
|
20
|
+
end
|
21
|
+
|
22
|
+
def call
|
23
|
+
content_or_options = nil
|
24
|
+
|
25
|
+
content_or_options = content || attribute_content if content.present? || attribute_content.present?
|
26
|
+
|
27
|
+
ActionView::Helpers::Tags::Label.new(object_name, method_name, @view_context, content_or_options,
|
28
|
+
options).render
|
29
|
+
end
|
30
|
+
|
31
|
+
# See: https://github.com/rails/rails/blob/83217025a171593547d1268651b446d3533e2019/actionview/lib/action_view/helpers/tags/label.rb#L48
|
32
|
+
def builder
|
33
|
+
@builder ||= begin
|
34
|
+
tag_value = options.delete("value")
|
35
|
+
|
36
|
+
ActionView::Helpers::Tags::Label::LabelBuilder.new(@view_context, object_name, method_name, object, tag_value)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
delegate :translation, to: :builder
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponent
|
4
|
+
module Form
|
5
|
+
class RadioButtonComponent < FieldComponent
|
6
|
+
self.tag_klass = ActionView::Helpers::Tags::RadioButton
|
7
|
+
|
8
|
+
attr_reader :value
|
9
|
+
|
10
|
+
def initialize(form, object_name, method_name, value, options = {})
|
11
|
+
@value = value
|
12
|
+
|
13
|
+
super(form, object_name, method_name, options)
|
14
|
+
end
|
15
|
+
|
16
|
+
def call
|
17
|
+
ActionView::Helpers::Tags::RadioButton.new(
|
18
|
+
object_name,
|
19
|
+
method_name,
|
20
|
+
@view_context,
|
21
|
+
value,
|
22
|
+
options
|
23
|
+
).render
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponent
|
4
|
+
module Form
|
5
|
+
class SelectComponent < FieldComponent
|
6
|
+
attr_reader :choices, :html_options
|
7
|
+
|
8
|
+
def initialize(form, object_name, method_name, choices = nil, options = {}, html_options = {}) # rubocop:disable Metrics/ParameterLists
|
9
|
+
@choices = choices
|
10
|
+
@html_options = html_options
|
11
|
+
|
12
|
+
super(form, object_name, method_name, options)
|
13
|
+
|
14
|
+
set_html_options!
|
15
|
+
end
|
16
|
+
|
17
|
+
def call
|
18
|
+
ActionView::Helpers::Tags::Select.new(
|
19
|
+
object_name,
|
20
|
+
method_name,
|
21
|
+
@view_context,
|
22
|
+
choices,
|
23
|
+
options,
|
24
|
+
html_options,
|
25
|
+
&content
|
26
|
+
).render
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
def set_html_options!
|
32
|
+
@html_options[:class] = class_names(html_options[:class], html_class)
|
33
|
+
@html_options.delete(:class) if @html_options[:class].blank?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponent
|
4
|
+
module Form
|
5
|
+
class SubmitComponent < BaseComponent
|
6
|
+
attr_reader :value
|
7
|
+
|
8
|
+
def initialize(form, value, options = {})
|
9
|
+
@value = value
|
10
|
+
|
11
|
+
super(form, nil, options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def call
|
15
|
+
submit_tag(value, options)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|