view_component-form 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|