view_component-form 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -2
- data/README.md +39 -23
- data/app/components/view_component/form/base_component.rb +4 -2
- data/app/components/view_component/form/field_component.rb +14 -5
- data/lib/view_component/form/builder.rb +22 -15
- data/lib/view_component/form/class_names_helper.rb +2 -0
- data/lib/view_component/form/test_helpers.rb +10 -6
- data/lib/view_component/form/version.rb +1 -1
- metadata +7 -7
- data/app/components/view_component/form/datetime_field_component.rb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 85efb54495b971620e090764d16af0253225b448f47cd65e688e45d5b156ff2d
|
4
|
+
data.tar.gz: ba85d7de360b93c16e1c74868169c82e555290b0d783427a77e61cad46e9b129
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1cb013fe12f393f641faa269d38268f5bd3a3c959078c33b5266c0612c1f046d24a2354e3b8b1dbf4d635cd8cfdb0da9d455b3fd1b4bd6aac2456cdd9a44316e
|
7
|
+
data.tar.gz: 44c37beaaed85850e70819cd0b6df1f7f14ce6edb79e334f3fcdc4f2b232e78374f9463b4f8ad84047689f1a46e08dcf9a392a1d788f7a19228efdfbe04e2ee2
|
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,28 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
|
+
Nothing yet
|
9
|
+
|
10
|
+
## [0.1.2] - 2021-12-07
|
11
|
+
### Added
|
12
|
+
- Add missing component specs (#75)
|
13
|
+
- Add missing builder specs for return values (#76)
|
14
|
+
- Add accurate test cases for all helpers from ActionView::Helpers::FormBuilder
|
15
|
+
documentation (#85)
|
16
|
+
|
17
|
+
### Changed
|
18
|
+
- Cross-documented Rails form helpers (#84)
|
19
|
+
- Made tag_klass optional when inheriting from a component class (#87)
|
20
|
+
- Improve README: generator, html_class example (#88)
|
21
|
+
- Make rails version condition used the same way (#92)
|
22
|
+
- Add rails 7.0 and make rails head works (#94)
|
23
|
+
- Allow `Base` and `FieldComponent` to support forms without objects (#95)
|
24
|
+
|
25
|
+
### Fixed
|
26
|
+
- Fix `phone_field` helper (#74)
|
27
|
+
- Fix `datetime_local_field` helper (#76)
|
28
|
+
- Fix `time_zone_select` helper (#76)
|
29
|
+
- Resolve Rails 6.1 deprecation on ActiveModel::Errors#keys call (#91)
|
8
30
|
|
9
31
|
## [0.1.1] - 2021-09-27
|
10
32
|
|
@@ -17,7 +39,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
17
39
|
## [0.1.0] - 2021-09-16
|
18
40
|
|
19
41
|
### Added
|
20
|
-
|
21
42
|
- `FormBuilder`: add `.namespace` method to allow local lookup of components (#54)
|
22
43
|
- Add basic `ViewComponent::Form::Builder` that can be used in place of Rails' `ActionView::Helpers::FormBuilder` (#1)
|
23
44
|
- Add all standard FormBuilder helpers provided by Rails, implemented as ViewComponents (#4)
|
@@ -25,6 +46,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
25
46
|
- Add CHANGELOG (#50)
|
26
47
|
- Add CI (#2)
|
27
48
|
|
28
|
-
[Unreleased]: https://github.com/pantographe/view_component-form/compare/v0.1.
|
49
|
+
[Unreleased]: https://github.com/pantographe/view_component-form/compare/v0.1.2...HEAD
|
50
|
+
[0.1.2]: https://github.com/pantographe/view_component-form/compare/v0.1.1...v0.1.2
|
29
51
|
[0.1.1]: https://github.com/pantographe/view_component-form/compare/v0.1.0...v0.1.1
|
30
52
|
[0.1.0]: https://github.com/pantographe/view_component-form/releases/tag/v0.1.0
|
data/README.md
CHANGED
@@ -24,7 +24,7 @@ And then execute:
|
|
24
24
|
|
25
25
|
## Usage
|
26
26
|
|
27
|
-
Add a `builder` param to your `form_for`
|
27
|
+
Add a `builder` param to your `form_for`, `form_with`, `fields_for` or `fields`:
|
28
28
|
|
29
29
|
```diff
|
30
30
|
- <%= form_for @user do |f| %>
|
@@ -64,10 +64,10 @@ It should work out of the box, but does nothing particularly interesting for now
|
|
64
64
|
|
65
65
|
<label for="user_last_name">Last name</label>
|
66
66
|
<input type="text" value="Doe" name="user[last_name]" id="user_last_name" />
|
67
|
-
|
67
|
+
|
68
68
|
<label for="user_email">E-mail</label>
|
69
69
|
<input type="email" value="john.doe@example.com" name="user[email]" id="user_email" />
|
70
|
-
|
70
|
+
|
71
71
|
<label for="user_password">Password</label>
|
72
72
|
<input type="password" name="user[password]" id="user_password" />
|
73
73
|
</form>
|
@@ -91,14 +91,14 @@ This allows you to pick the namespace your components will be loaded from.
|
|
91
91
|
# lib/custom_form_builder.rb
|
92
92
|
class CustomFormBuilder < ViewComponent::Form::Builder
|
93
93
|
# Set the namespace you want to use for your own components
|
94
|
-
namespace Form
|
94
|
+
namespace Custom::Form
|
95
95
|
end
|
96
96
|
```
|
97
97
|
|
98
|
-
|
98
|
+
Use the generator options to change the default namespace or the path where the file will be created:
|
99
99
|
|
100
100
|
```console
|
101
|
-
bin/rails generate vcf:builder AnotherCustomFormBuilder --namespace
|
101
|
+
bin/rails generate vcf:builder AnotherCustomFormBuilder --namespace AnotherCustom::Form --path app/forms
|
102
102
|
|
103
103
|
create app/forms/another_custom_form_builder.rb
|
104
104
|
```
|
@@ -107,23 +107,22 @@ bin/rails generate vcf:builder AnotherCustomFormBuilder --namespace Forms::Compo
|
|
107
107
|
# app/forms/another_custom_form_builder.rb
|
108
108
|
class AnotherCustomFormBuilder < ViewComponent::Form::Builder
|
109
109
|
# Set the namespace you want to use for your own components
|
110
|
-
namespace
|
110
|
+
namespace AnotherCustom::Form
|
111
111
|
end
|
112
112
|
```
|
113
113
|
|
114
|
-
|
115
|
-
|
116
|
-
Now let's generate your own components to customize the rendering.
|
114
|
+
Now let's generate your own components to customize their rendering. We can use the standard view_component generator:
|
117
115
|
|
118
116
|
```console
|
119
|
-
bin/rails generate
|
117
|
+
bin/rails generate component Custom::Form::TextField --inline --parent ViewComponent::Form::TextFieldComponent
|
120
118
|
|
121
119
|
invoke test_unit
|
122
|
-
create test/components/form/text_field_component_test.rb
|
123
|
-
create app/components/form/text_field_component.rb
|
124
|
-
create app/components/form/text_field_component.html.erb
|
120
|
+
create test/components/custom/form/text_field_component_test.rb
|
121
|
+
create app/components/custom/form/text_field_component.rb
|
125
122
|
```
|
126
123
|
|
124
|
+
:warning: The `--parent` option is available since ViewComponent [`v2.41.0`](https://viewcomponent.org/CHANGELOG.html#2410). If you're using a previous version, you can always edit the generated `Custom::Form::CustomTextFieldComponent` class to make it inherit from `ViewComponent::Form::TextFieldComponent`.
|
125
|
+
|
127
126
|
Change your forms to use your new builder:
|
128
127
|
|
129
128
|
```diff
|
@@ -131,26 +130,43 @@ Change your forms to use your new builder:
|
|
131
130
|
+ <%= form_for @user, builder: CustomFormBuilder do |f| %>
|
132
131
|
```
|
133
132
|
|
134
|
-
You can then customize the behavior of your `Form::
|
133
|
+
You can then customize the behavior of your `Custom::Form::CustomTextFieldComponent`:
|
135
134
|
|
136
135
|
```rb
|
137
|
-
# app/components/form/text_field_component.rb
|
136
|
+
# app/components/custom/form/text_field_component.rb
|
138
137
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
class_names("text-field", "border-error": method_errors?)
|
143
|
-
end
|
138
|
+
class Admin::Form::TextFieldComponent < ViewComponent::Form::TextFieldComponent
|
139
|
+
def html_class
|
140
|
+
class_names("custom-text-field", "has-error": method_errors?)
|
144
141
|
end
|
145
142
|
end
|
146
143
|
```
|
147
144
|
|
148
|
-
|
145
|
+
In this case we leverage the [`#class_names`](https://api.rubyonrails.org/classes/ActionView/Helpers/TagHelper.html#method-i-class_names) helper to:
|
146
|
+
- always add the `custom-text-field` class;
|
147
|
+
- add the `has-error` class if there is an error on the attribute (using `ViewComponent::Form::FieldComponent#method_errors?`).
|
148
|
+
|
149
|
+
The rendered form field will now look like this:
|
149
150
|
|
150
151
|
```html
|
151
|
-
<input class="text-field" type="text" value="John" name="user[first_name]" id="user_first_name">
|
152
|
+
<input class="custom-text-field" type="text" value="John" name="user[first_name]" id="user_first_name">
|
152
153
|
```
|
153
154
|
|
155
|
+
You can use the same approach to inject options, wrap the input in a `<div>`, etc.
|
156
|
+
|
157
|
+
We'll add more use cases to the documentation soon.
|
158
|
+
|
159
|
+
### Using your form components without a backing model
|
160
|
+
|
161
|
+
If you want to ensure that your fields display consistently across your app, you'll need to lean on Rails' own helpers. You may be used to using form tag helpers such as `text_field_tag` to generate tags, or even writing out plain HTML tags. These can't be integrated with a form builder, so they won't offer you the benefits of this gem.
|
162
|
+
|
163
|
+
You'll most likely want to use either:
|
164
|
+
|
165
|
+
- [`form_with`](https://api.rubyonrails.org/v6.1.4/classes/ActionView/Helpers/FormHelper.html#method-i-form_with) and supply a route as the endpoint, e.g. `form_with url: users_path do |f| ...`, or
|
166
|
+
- [`fields`](https://api.rubyonrails.org/v6.1.4/classes/ActionView/Helpers/FormHelper.html#method-i-fields), supplying a namespace if necessary. `fields do |f| ...` ought to work in the most basic case.
|
167
|
+
|
168
|
+
[`fields_for`](https://api.rubyonrails.org/v6.1.4/classes/ActionView/Helpers/FormHelper.html#method-i-fields_for) may also be of interest. To make consistent use of `view_component-form`, you'll want to be using these three helpers to build your forms wherever possible.
|
169
|
+
|
154
170
|
## Development
|
155
171
|
|
156
172
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
@@ -14,8 +14,8 @@ module ViewComponent
|
|
14
14
|
|
15
15
|
attr_reader :form, :object_name, :options
|
16
16
|
|
17
|
-
delegate :object, to: :form
|
18
|
-
delegate :errors, to: :object, prefix: true
|
17
|
+
delegate :object, to: :form, allow_nil: true
|
18
|
+
delegate :errors, to: :object, prefix: true, allow_nil: true
|
19
19
|
|
20
20
|
def initialize(form, object_name, options = {})
|
21
21
|
@form = form
|
@@ -28,6 +28,8 @@ module ViewComponent
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def object_errors?
|
31
|
+
return false unless object
|
32
|
+
|
31
33
|
object.errors.any?
|
32
34
|
end
|
33
35
|
|
@@ -3,9 +3,8 @@
|
|
3
3
|
module ViewComponent
|
4
4
|
module Form
|
5
5
|
class FieldComponent < BaseComponent
|
6
|
-
|
7
|
-
|
8
|
-
end
|
6
|
+
class_attribute :tag_klass, instance_reader: false, instance_writer: false, instance_accessor: false,
|
7
|
+
instance_predicate: false
|
9
8
|
|
10
9
|
attr_reader :method_name
|
11
10
|
|
@@ -31,8 +30,18 @@ module ViewComponent
|
|
31
30
|
.map(&:upcase_first)
|
32
31
|
end
|
33
32
|
|
34
|
-
|
35
|
-
|
33
|
+
if Gem::Version.new(Rails::VERSION::STRING) >= Gem::Version.new("6.1")
|
34
|
+
def method_errors?
|
35
|
+
return false unless object_errors
|
36
|
+
|
37
|
+
(object_errors.attribute_names & object_method_names).any?
|
38
|
+
end
|
39
|
+
else
|
40
|
+
def method_errors?
|
41
|
+
return false unless object_errors
|
42
|
+
|
43
|
+
(object_errors.keys & object_method_names).any?
|
44
|
+
end
|
36
45
|
end
|
37
46
|
|
38
47
|
def value
|
@@ -35,7 +35,18 @@ module ViewComponent
|
|
35
35
|
super
|
36
36
|
end
|
37
37
|
|
38
|
-
(field_helpers - %i[
|
38
|
+
(field_helpers - %i[
|
39
|
+
check_box
|
40
|
+
datetime_field
|
41
|
+
datetime_local_field
|
42
|
+
fields
|
43
|
+
fields_for
|
44
|
+
file_field
|
45
|
+
hidden_field
|
46
|
+
label
|
47
|
+
phone_field
|
48
|
+
radio_button
|
49
|
+
]).each do |selector|
|
39
50
|
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
|
40
51
|
def #{selector}(method, options = {}) # def text_field(method, options = {})
|
41
52
|
render_component( # render_component(
|
@@ -47,12 +58,20 @@ module ViewComponent
|
|
47
58
|
end # end
|
48
59
|
RUBY_EVAL
|
49
60
|
end
|
61
|
+
alias phone_field telephone_field
|
50
62
|
|
51
63
|
# See: https://github.com/rails/rails/blob/33d60cb02dcac26d037332410eabaeeb0bdc384c/actionview/lib/action_view/helpers/form_helper.rb#L2280
|
52
64
|
def label(method, text = nil, options = {}, &block)
|
53
65
|
render_component(:label, @object_name, method, text, objectify_options(options), &block)
|
54
66
|
end
|
55
67
|
|
68
|
+
def datetime_field(method, options = {})
|
69
|
+
render_component(
|
70
|
+
:datetime_local_field, @object_name, method, objectify_options(options)
|
71
|
+
)
|
72
|
+
end
|
73
|
+
alias datetime_locale_field datetime_field
|
74
|
+
|
56
75
|
def check_box(method, options = {}, checked_value = "1", unchecked_value = "0")
|
57
76
|
render_component(
|
58
77
|
:check_box, @object_name, method, checked_value, unchecked_value, objectify_options(options)
|
@@ -88,18 +107,6 @@ module ViewComponent
|
|
88
107
|
render_component(:button, value, options, &block)
|
89
108
|
end
|
90
109
|
|
91
|
-
# SELECTORS.each do |selector|
|
92
|
-
# class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
|
93
|
-
# def #{selector}(*args)
|
94
|
-
# render_component(
|
95
|
-
# :#{selector},
|
96
|
-
# *args,
|
97
|
-
# super,
|
98
|
-
# )
|
99
|
-
# end
|
100
|
-
# RUBY_EVAL
|
101
|
-
# end
|
102
|
-
|
103
110
|
# See: https://github.com/rails/rails/blob/fe76a95b0d252a2d7c25e69498b720c96b243ea2/actionview/lib/action_view/helpers/form_options_helper.rb
|
104
111
|
def select(method, choices = nil, options = {}, html_options = {}, &block)
|
105
112
|
render_component(
|
@@ -169,9 +176,9 @@ module ViewComponent
|
|
169
176
|
)
|
170
177
|
end
|
171
178
|
|
172
|
-
def time_zone_select(method, options = {}, html_options = {})
|
179
|
+
def time_zone_select(method, priority_zones = nil, options = {}, html_options = {})
|
173
180
|
render_component(
|
174
|
-
:time_zone_select, @object_name, method,
|
181
|
+
:time_zone_select, @object_name, method, priority_zones,
|
175
182
|
objectify_options(options), @default_html_options.merge(html_options)
|
176
183
|
)
|
177
184
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Backport of https://api.rubyonrails.org/classes/ActionView/Helpers/TagHelper.html#method-i-class_names
|
4
|
+
# :nocov:
|
4
5
|
module ViewComponent
|
5
6
|
module Form
|
6
7
|
module ClassNamesHelper
|
@@ -35,3 +36,4 @@ module ViewComponent
|
|
35
36
|
end
|
36
37
|
end
|
37
38
|
end
|
39
|
+
# :nocov:
|
@@ -7,20 +7,24 @@ require "action_view"
|
|
7
7
|
module ViewComponent
|
8
8
|
module Form
|
9
9
|
module TestHelpers
|
10
|
-
def form_with(object,
|
11
|
-
|
10
|
+
def form_with(object, builder: ViewComponent::Form::Builder, **options)
|
11
|
+
builder.new(object_name, object, template, options)
|
12
12
|
end
|
13
13
|
|
14
14
|
def object_name
|
15
15
|
:user
|
16
16
|
end
|
17
17
|
|
18
|
-
|
19
|
-
|
18
|
+
if Gem::Version.new(Rails::VERSION::STRING) >= Gem::Version.new("6.1")
|
19
|
+
def template
|
20
|
+
lookup_context = ActionView::LookupContext.new(ActionController::Base.view_paths)
|
20
21
|
|
21
|
-
if Gem::Version.new(Rails::VERSION::STRING) >= Gem::Version.new("6.1")
|
22
22
|
ActionView::Base.new(lookup_context, {}, ApplicationController.new)
|
23
|
-
|
23
|
+
end
|
24
|
+
else
|
25
|
+
def template
|
26
|
+
lookup_context = ActionView::LookupContext.new(ActionController::Base.view_paths)
|
27
|
+
|
24
28
|
ActionView::Base.new(lookup_context, {})
|
25
29
|
end
|
26
30
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: view_component-form
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pantographe
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-12-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionview
|
@@ -89,7 +89,6 @@ files:
|
|
89
89
|
- app/components/view_component/form/color_field_component.rb
|
90
90
|
- app/components/view_component/form/date_field_component.rb
|
91
91
|
- app/components/view_component/form/date_select_component.rb
|
92
|
-
- app/components/view_component/form/datetime_field_component.rb
|
93
92
|
- app/components/view_component/form/datetime_local_field_component.rb
|
94
93
|
- app/components/view_component/form/datetime_select_component.rb
|
95
94
|
- app/components/view_component/form/email_field_component.rb
|
@@ -130,7 +129,8 @@ metadata:
|
|
130
129
|
changelog_uri: https://github.com/pantographe/view_component-form/blob/master/CHANGELOG.md
|
131
130
|
source_code_uri: https://github.com/pantographe/view_component-form
|
132
131
|
bug_tracker_uri: https://github.com/pantographe/view_component-form/issues
|
133
|
-
|
132
|
+
rubygems_mfa_required: 'true'
|
133
|
+
post_install_message:
|
134
134
|
rdoc_options: []
|
135
135
|
require_paths:
|
136
136
|
- lib
|
@@ -145,8 +145,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
145
145
|
- !ruby/object:Gem::Version
|
146
146
|
version: '0'
|
147
147
|
requirements: []
|
148
|
-
rubygems_version: 3.2.
|
149
|
-
signing_key:
|
148
|
+
rubygems_version: 3.2.9
|
149
|
+
signing_key:
|
150
150
|
specification_version: 4
|
151
151
|
summary: Rails FormBuilder for ViewComponent
|
152
152
|
test_files: []
|