phlexi-form 0.2.0 → 0.3.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/Appraisals +4 -9
- data/README.md +117 -316
- data/TODO +4 -0
- data/config.ru +0 -3
- data/gemfiles/default.gemfile.lock +22 -2
- data/gemfiles/rails_7.gemfile +8 -0
- data/gemfiles/rails_7.gemfile.lock +282 -0
- data/lib/phlexi/form/base.rb +65 -56
- data/lib/phlexi/form/components/base.rb +14 -8
- data/lib/phlexi/form/components/checkbox.rb +5 -0
- data/lib/phlexi/form/components/collection_checkboxes.rb +28 -14
- data/lib/phlexi/form/components/collection_radio_buttons.rb +19 -13
- data/lib/phlexi/form/components/concerns/extracts_input.rb +53 -0
- data/lib/phlexi/form/components/concerns/handles_array_input.rb +21 -0
- data/lib/phlexi/form/components/concerns/handles_input.rb +23 -0
- data/lib/phlexi/form/components/concerns/has_options.rb +6 -2
- data/lib/phlexi/form/components/concerns/submits_form.rb +47 -0
- data/lib/phlexi/form/components/error.rb +1 -1
- data/lib/phlexi/form/components/file_input.rb +33 -0
- data/lib/phlexi/form/components/hint.rb +1 -1
- data/lib/phlexi/form/components/input.rb +38 -36
- data/lib/phlexi/form/components/input_array.rb +45 -0
- data/lib/phlexi/form/components/label.rb +2 -1
- data/lib/phlexi/form/components/radio_button.rb +11 -1
- data/lib/phlexi/form/components/select.rb +21 -8
- data/lib/phlexi/form/components/submit_button.rb +41 -0
- data/lib/phlexi/form/components/textarea.rb +2 -3
- data/lib/phlexi/form/field_options/associations.rb +21 -0
- data/lib/phlexi/form/field_options/autofocus.rb +1 -1
- data/lib/phlexi/form/field_options/collection.rb +26 -9
- data/lib/phlexi/form/field_options/errors.rb +17 -3
- data/lib/phlexi/form/field_options/hints.rb +5 -1
- data/lib/phlexi/form/field_options/{type.rb → inferred_types.rb} +21 -17
- data/lib/phlexi/form/field_options/multiple.rb +2 -0
- data/lib/phlexi/form/field_options/required.rb +1 -1
- data/lib/phlexi/form/field_options/themes.rb +207 -0
- data/lib/phlexi/form/field_options/validators.rb +2 -2
- data/lib/phlexi/form/option_mapper.rb +2 -2
- data/lib/phlexi/form/structure/dom.rb +21 -16
- data/lib/phlexi/form/structure/field_builder.rb +165 -121
- data/lib/phlexi/form/structure/field_collection.rb +20 -6
- data/lib/phlexi/form/structure/namespace.rb +48 -31
- data/lib/phlexi/form/structure/namespace_collection.rb +20 -20
- data/lib/phlexi/form/structure/node.rb +13 -3
- data/lib/phlexi/form/version.rb +1 -1
- data/lib/phlexi/form.rb +4 -1
- metadata +32 -7
- data/CODE_OF_CONDUCT.md +0 -84
@@ -0,0 +1,282 @@
|
|
1
|
+
PATH
|
2
|
+
remote: ..
|
3
|
+
specs:
|
4
|
+
phlexi-form (0.3.0.rc1)
|
5
|
+
activesupport
|
6
|
+
phlex (~> 1.11)
|
7
|
+
zeitwerk
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://rubygems.org/
|
11
|
+
specs:
|
12
|
+
actioncable (7.1.3.4)
|
13
|
+
actionpack (= 7.1.3.4)
|
14
|
+
activesupport (= 7.1.3.4)
|
15
|
+
nio4r (~> 2.0)
|
16
|
+
websocket-driver (>= 0.6.1)
|
17
|
+
zeitwerk (~> 2.6)
|
18
|
+
actionmailbox (7.1.3.4)
|
19
|
+
actionpack (= 7.1.3.4)
|
20
|
+
activejob (= 7.1.3.4)
|
21
|
+
activerecord (= 7.1.3.4)
|
22
|
+
activestorage (= 7.1.3.4)
|
23
|
+
activesupport (= 7.1.3.4)
|
24
|
+
mail (>= 2.7.1)
|
25
|
+
net-imap
|
26
|
+
net-pop
|
27
|
+
net-smtp
|
28
|
+
actionmailer (7.1.3.4)
|
29
|
+
actionpack (= 7.1.3.4)
|
30
|
+
actionview (= 7.1.3.4)
|
31
|
+
activejob (= 7.1.3.4)
|
32
|
+
activesupport (= 7.1.3.4)
|
33
|
+
mail (~> 2.5, >= 2.5.4)
|
34
|
+
net-imap
|
35
|
+
net-pop
|
36
|
+
net-smtp
|
37
|
+
rails-dom-testing (~> 2.2)
|
38
|
+
actionpack (7.1.3.4)
|
39
|
+
actionview (= 7.1.3.4)
|
40
|
+
activesupport (= 7.1.3.4)
|
41
|
+
nokogiri (>= 1.8.5)
|
42
|
+
racc
|
43
|
+
rack (>= 2.2.4)
|
44
|
+
rack-session (>= 1.0.1)
|
45
|
+
rack-test (>= 0.6.3)
|
46
|
+
rails-dom-testing (~> 2.2)
|
47
|
+
rails-html-sanitizer (~> 1.6)
|
48
|
+
actiontext (7.1.3.4)
|
49
|
+
actionpack (= 7.1.3.4)
|
50
|
+
activerecord (= 7.1.3.4)
|
51
|
+
activestorage (= 7.1.3.4)
|
52
|
+
activesupport (= 7.1.3.4)
|
53
|
+
globalid (>= 0.6.0)
|
54
|
+
nokogiri (>= 1.8.5)
|
55
|
+
actionview (7.1.3.4)
|
56
|
+
activesupport (= 7.1.3.4)
|
57
|
+
builder (~> 3.1)
|
58
|
+
erubi (~> 1.11)
|
59
|
+
rails-dom-testing (~> 2.2)
|
60
|
+
rails-html-sanitizer (~> 1.6)
|
61
|
+
activejob (7.1.3.4)
|
62
|
+
activesupport (= 7.1.3.4)
|
63
|
+
globalid (>= 0.3.6)
|
64
|
+
activemodel (7.1.3.4)
|
65
|
+
activesupport (= 7.1.3.4)
|
66
|
+
activerecord (7.1.3.4)
|
67
|
+
activemodel (= 7.1.3.4)
|
68
|
+
activesupport (= 7.1.3.4)
|
69
|
+
timeout (>= 0.4.0)
|
70
|
+
activestorage (7.1.3.4)
|
71
|
+
actionpack (= 7.1.3.4)
|
72
|
+
activejob (= 7.1.3.4)
|
73
|
+
activerecord (= 7.1.3.4)
|
74
|
+
activesupport (= 7.1.3.4)
|
75
|
+
marcel (~> 1.0)
|
76
|
+
activesupport (7.1.3.4)
|
77
|
+
base64
|
78
|
+
bigdecimal
|
79
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
80
|
+
connection_pool (>= 2.2.5)
|
81
|
+
drb
|
82
|
+
i18n (>= 1.6, < 2)
|
83
|
+
minitest (>= 5.1)
|
84
|
+
mutex_m
|
85
|
+
tzinfo (~> 2.0)
|
86
|
+
addressable (2.8.7)
|
87
|
+
public_suffix (>= 2.0.2, < 7.0)
|
88
|
+
ansi (1.5.0)
|
89
|
+
appraisal (2.5.0)
|
90
|
+
bundler
|
91
|
+
rake
|
92
|
+
thor (>= 0.14.0)
|
93
|
+
ast (2.4.2)
|
94
|
+
base64 (0.2.0)
|
95
|
+
bigdecimal (3.1.8)
|
96
|
+
builder (3.3.0)
|
97
|
+
bundle-audit (0.1.0)
|
98
|
+
bundler-audit
|
99
|
+
bundler-audit (0.9.1)
|
100
|
+
bundler (>= 1.2.0, < 3)
|
101
|
+
thor (~> 1.0)
|
102
|
+
capybara (3.40.0)
|
103
|
+
addressable
|
104
|
+
matrix
|
105
|
+
mini_mime (>= 0.1.3)
|
106
|
+
nokogiri (~> 1.11)
|
107
|
+
rack (>= 1.6.0)
|
108
|
+
rack-test (>= 0.6.3)
|
109
|
+
regexp_parser (>= 1.5, < 3.0)
|
110
|
+
xpath (~> 3.2)
|
111
|
+
combustion (1.5.0)
|
112
|
+
activesupport (>= 3.0.0)
|
113
|
+
railties (>= 3.0.0)
|
114
|
+
thor (>= 0.14.6)
|
115
|
+
concurrent-ruby (1.3.3)
|
116
|
+
connection_pool (2.4.1)
|
117
|
+
crass (1.0.6)
|
118
|
+
date (3.3.4)
|
119
|
+
drb (2.2.1)
|
120
|
+
erubi (1.13.0)
|
121
|
+
globalid (1.2.1)
|
122
|
+
activesupport (>= 6.1)
|
123
|
+
i18n (1.14.5)
|
124
|
+
concurrent-ruby (~> 1.0)
|
125
|
+
io-console (0.7.2)
|
126
|
+
irb (1.14.0)
|
127
|
+
rdoc (>= 4.0.0)
|
128
|
+
reline (>= 0.4.2)
|
129
|
+
json (2.7.2)
|
130
|
+
language_server-protocol (3.17.0.3)
|
131
|
+
lint_roller (1.1.0)
|
132
|
+
loofah (2.22.0)
|
133
|
+
crass (~> 1.0.2)
|
134
|
+
nokogiri (>= 1.12.0)
|
135
|
+
mail (2.8.1)
|
136
|
+
mini_mime (>= 0.1.1)
|
137
|
+
net-imap
|
138
|
+
net-pop
|
139
|
+
net-smtp
|
140
|
+
marcel (1.0.4)
|
141
|
+
matrix (0.4.2)
|
142
|
+
mini_mime (1.1.5)
|
143
|
+
minitest (5.24.1)
|
144
|
+
minitest-reporters (1.7.1)
|
145
|
+
ansi
|
146
|
+
builder
|
147
|
+
minitest (>= 5.0)
|
148
|
+
ruby-progressbar
|
149
|
+
mutex_m (0.2.0)
|
150
|
+
net-imap (0.4.14)
|
151
|
+
date
|
152
|
+
net-protocol
|
153
|
+
net-pop (0.1.2)
|
154
|
+
net-protocol
|
155
|
+
net-protocol (0.2.2)
|
156
|
+
timeout
|
157
|
+
net-smtp (0.5.0)
|
158
|
+
net-protocol
|
159
|
+
nio4r (2.7.3)
|
160
|
+
nokogiri (1.16.7-x86_64-darwin)
|
161
|
+
racc (~> 1.4)
|
162
|
+
parallel (1.25.1)
|
163
|
+
parser (3.3.4.0)
|
164
|
+
ast (~> 2.4.1)
|
165
|
+
racc
|
166
|
+
phlex (1.11.0)
|
167
|
+
phlex-testing-capybara (0.1.0)
|
168
|
+
capybara (~> 3.38)
|
169
|
+
phlex (>= 0.5)
|
170
|
+
psych (5.1.2)
|
171
|
+
stringio
|
172
|
+
public_suffix (6.0.1)
|
173
|
+
racc (1.8.1)
|
174
|
+
rack (3.1.7)
|
175
|
+
rack-session (2.0.0)
|
176
|
+
rack (>= 3.0.0)
|
177
|
+
rack-test (2.1.0)
|
178
|
+
rack (>= 1.3)
|
179
|
+
rackup (2.1.0)
|
180
|
+
rack (>= 3)
|
181
|
+
webrick (~> 1.8)
|
182
|
+
rails (7.1.3.4)
|
183
|
+
actioncable (= 7.1.3.4)
|
184
|
+
actionmailbox (= 7.1.3.4)
|
185
|
+
actionmailer (= 7.1.3.4)
|
186
|
+
actionpack (= 7.1.3.4)
|
187
|
+
actiontext (= 7.1.3.4)
|
188
|
+
actionview (= 7.1.3.4)
|
189
|
+
activejob (= 7.1.3.4)
|
190
|
+
activemodel (= 7.1.3.4)
|
191
|
+
activerecord (= 7.1.3.4)
|
192
|
+
activestorage (= 7.1.3.4)
|
193
|
+
activesupport (= 7.1.3.4)
|
194
|
+
bundler (>= 1.15.0)
|
195
|
+
railties (= 7.1.3.4)
|
196
|
+
rails-dom-testing (2.2.0)
|
197
|
+
activesupport (>= 5.0.0)
|
198
|
+
minitest
|
199
|
+
nokogiri (>= 1.6)
|
200
|
+
rails-html-sanitizer (1.6.0)
|
201
|
+
loofah (~> 2.21)
|
202
|
+
nokogiri (~> 1.14)
|
203
|
+
railties (7.1.3.4)
|
204
|
+
actionpack (= 7.1.3.4)
|
205
|
+
activesupport (= 7.1.3.4)
|
206
|
+
irb
|
207
|
+
rackup (>= 1.0.0)
|
208
|
+
rake (>= 12.2)
|
209
|
+
thor (~> 1.0, >= 1.2.2)
|
210
|
+
zeitwerk (~> 2.6)
|
211
|
+
rainbow (3.1.1)
|
212
|
+
rake (13.2.1)
|
213
|
+
rdoc (6.7.0)
|
214
|
+
psych (>= 4.0.0)
|
215
|
+
regexp_parser (2.9.2)
|
216
|
+
reline (0.5.9)
|
217
|
+
io-console (~> 0.5)
|
218
|
+
rexml (3.3.2)
|
219
|
+
strscan
|
220
|
+
rubocop (1.64.1)
|
221
|
+
json (~> 2.3)
|
222
|
+
language_server-protocol (>= 3.17.0)
|
223
|
+
parallel (~> 1.10)
|
224
|
+
parser (>= 3.3.0.2)
|
225
|
+
rainbow (>= 2.2.2, < 4.0)
|
226
|
+
regexp_parser (>= 1.8, < 3.0)
|
227
|
+
rexml (>= 3.2.5, < 4.0)
|
228
|
+
rubocop-ast (>= 1.31.1, < 2.0)
|
229
|
+
ruby-progressbar (~> 1.7)
|
230
|
+
unicode-display_width (>= 2.4.0, < 3.0)
|
231
|
+
rubocop-ast (1.31.3)
|
232
|
+
parser (>= 3.3.1.0)
|
233
|
+
rubocop-performance (1.21.1)
|
234
|
+
rubocop (>= 1.48.1, < 2.0)
|
235
|
+
rubocop-ast (>= 1.31.1, < 2.0)
|
236
|
+
ruby-progressbar (1.13.0)
|
237
|
+
sqlite3 (1.7.3-x86_64-darwin)
|
238
|
+
standard (1.39.2)
|
239
|
+
language_server-protocol (~> 3.17.0.2)
|
240
|
+
lint_roller (~> 1.0)
|
241
|
+
rubocop (~> 1.64.0)
|
242
|
+
standard-custom (~> 1.0.0)
|
243
|
+
standard-performance (~> 1.4)
|
244
|
+
standard-custom (1.0.2)
|
245
|
+
lint_roller (~> 1.0)
|
246
|
+
rubocop (~> 1.50)
|
247
|
+
standard-performance (1.4.0)
|
248
|
+
lint_roller (~> 1.1)
|
249
|
+
rubocop-performance (~> 1.21.0)
|
250
|
+
stringio (3.1.1)
|
251
|
+
strscan (3.1.0)
|
252
|
+
thor (1.3.1)
|
253
|
+
timeout (0.4.1)
|
254
|
+
tzinfo (2.0.6)
|
255
|
+
concurrent-ruby (~> 1.0)
|
256
|
+
unicode-display_width (2.5.0)
|
257
|
+
webrick (1.8.1)
|
258
|
+
websocket-driver (0.7.6)
|
259
|
+
websocket-extensions (>= 0.1.0)
|
260
|
+
websocket-extensions (0.1.5)
|
261
|
+
xpath (3.2.0)
|
262
|
+
nokogiri (~> 1.8)
|
263
|
+
zeitwerk (2.6.17)
|
264
|
+
|
265
|
+
PLATFORMS
|
266
|
+
x86_64-darwin
|
267
|
+
|
268
|
+
DEPENDENCIES
|
269
|
+
appraisal
|
270
|
+
bundle-audit
|
271
|
+
combustion
|
272
|
+
minitest
|
273
|
+
minitest-reporters
|
274
|
+
phlex-testing-capybara
|
275
|
+
phlexi-form!
|
276
|
+
rails (~> 7.1.3, >= 7.1.3.4)
|
277
|
+
rake
|
278
|
+
sqlite3 (~> 1.4)
|
279
|
+
standard
|
280
|
+
|
281
|
+
BUNDLED WITH
|
282
|
+
2.5.16
|
data/lib/phlexi/form/base.rb
CHANGED
@@ -1,28 +1,30 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "action_view/model_naming"
|
4
3
|
require "active_support/core_ext/module/delegation"
|
5
4
|
require "active_support/string_inquirer"
|
6
|
-
require "active_support/core_ext/
|
5
|
+
require "active_support/core_ext/hash/deep_merge"
|
6
|
+
require "active_support/core_ext/string/inflections"
|
7
7
|
|
8
8
|
module Phlexi
|
9
9
|
module Form
|
10
10
|
# A form component for building flexible and customizable forms.
|
11
11
|
#
|
12
12
|
# @example Basic usage
|
13
|
-
# Form
|
14
|
-
#
|
15
|
-
#
|
13
|
+
# Phlexi::Form(user, action: '/users', method: 'post') do
|
14
|
+
# render field(:name).placeholder("Name").input_tag
|
15
|
+
# render field(:email).placeholder("Email").input_tag
|
16
16
|
# end
|
17
17
|
#
|
18
18
|
# @attr_reader [Symbol] key The form's key, derived from the record or explicitly set
|
19
19
|
# @attr_reader [ActiveModel::Model, nil] object The form's associated object
|
20
|
-
class Base <
|
21
|
-
|
20
|
+
class Base < COMPONENT_BASE
|
21
|
+
class Namespace < Structure::Namespace; end
|
22
|
+
|
23
|
+
class FieldBuilder < Structure::FieldBuilder; end
|
22
24
|
|
23
25
|
attr_reader :key, :object
|
24
26
|
|
25
|
-
delegate :field, :nest_one, :nest_many, to: :@namespace
|
27
|
+
delegate :field, :submit_button, :nest_one, :nest_many, to: :@namespace
|
26
28
|
|
27
29
|
# Initializes a new Form instance.
|
28
30
|
#
|
@@ -39,6 +41,8 @@ module Phlexi
|
|
39
41
|
@form_method = method
|
40
42
|
@form_class = options.delete(:class)
|
41
43
|
@attributes = attributes
|
44
|
+
@namespace_klass = options.delete(:namespace_klass) || default_namespace_klass
|
45
|
+
@builder_klass = options.delete(:builder_klass) || default_builder_klass
|
42
46
|
@options = options
|
43
47
|
|
44
48
|
initialize_object_and_key(record)
|
@@ -61,40 +65,36 @@ module Phlexi
|
|
61
65
|
instance_exec(&@_content_block) if @_content_block
|
62
66
|
end
|
63
67
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
# @return [void]
|
68
|
-
def form_tag(&block)
|
69
|
-
form(**form_attributes) do
|
70
|
-
render_hidden_method_field
|
71
|
-
render_authenticity_token if authenticity_token?
|
72
|
-
yield
|
73
|
-
end
|
68
|
+
def extract_input(params)
|
69
|
+
call unless @_rendered
|
70
|
+
@namespace.extract_input(params)
|
74
71
|
end
|
75
72
|
|
76
73
|
protected
|
77
74
|
|
78
|
-
attr_reader :options, :attributes
|
75
|
+
attr_reader :options, :attributes, :namespace_klass, :builder_klass
|
79
76
|
|
80
77
|
# Initializes the object and key based on the given record.
|
81
78
|
#
|
82
79
|
# @param record [ActiveModel::Model, Symbol, String] The form's associated record or key
|
83
80
|
# @return [void]
|
84
81
|
def initialize_object_and_key(record)
|
82
|
+
# always pop these keys
|
83
|
+
# add support for `as` to make it more rails friendly
|
84
|
+
@key = options.delete(:key) || options.delete(:as)
|
85
|
+
|
85
86
|
case record
|
86
87
|
when String, Symbol
|
87
88
|
@object = nil
|
88
89
|
@key = record
|
89
90
|
else
|
90
|
-
@object =
|
91
|
-
@key = options.delete(:as)
|
92
|
-
|
91
|
+
@object = record
|
93
92
|
if @key.nil?
|
94
|
-
|
95
|
-
|
93
|
+
@key = if object.respond_to?(:model_name) && object.model_name.respond_to?(:param_key) && object.model_name.param_key.present?
|
94
|
+
object.model_name.param_key
|
95
|
+
else
|
96
|
+
object.class.name.demodulize.underscore
|
96
97
|
end
|
97
|
-
@key = object.model_name.param_key
|
98
98
|
end
|
99
99
|
end
|
100
100
|
@key = @key.to_sym
|
@@ -111,7 +111,24 @@ module Phlexi
|
|
111
111
|
#
|
112
112
|
# @return [void]
|
113
113
|
def initialize_attributes
|
114
|
-
attributes[:accept_charset]
|
114
|
+
attributes.fetch(:accept_charset) { attributes[:accept_charset] = "UTF-8" }
|
115
|
+
end
|
116
|
+
|
117
|
+
# Retrieves the form's CSS classes.
|
118
|
+
#
|
119
|
+
# @return [String] The form's CSS classes
|
120
|
+
attr_reader :form_class
|
121
|
+
|
122
|
+
# Renders the form tag with its contents.
|
123
|
+
#
|
124
|
+
# @yield The form's content
|
125
|
+
# @return [void]
|
126
|
+
def form_tag(&)
|
127
|
+
form(**form_attributes) do
|
128
|
+
render_hidden_method_field
|
129
|
+
render_authenticity_token if has_authenticity_token?
|
130
|
+
yield
|
131
|
+
end
|
115
132
|
end
|
116
133
|
|
117
134
|
# Determines the form's action URL.
|
@@ -137,18 +154,11 @@ module Phlexi
|
|
137
154
|
ActiveSupport::StringInquirer.new(@form_method)
|
138
155
|
end
|
139
156
|
|
140
|
-
# Retrieves the form's CSS classes.
|
141
|
-
#
|
142
|
-
# @return [String] The form's CSS classes
|
143
|
-
def form_class
|
144
|
-
@form_class || "flex flex-col space-y-6 px-4 py-2"
|
145
|
-
end
|
146
|
-
|
147
157
|
# Checks if the authenticity token should be included.
|
148
158
|
#
|
149
159
|
# @return [Boolean] True if the authenticity token should be included, false otherwise
|
150
|
-
def
|
151
|
-
defined?(helpers) && options
|
160
|
+
def has_authenticity_token?
|
161
|
+
!form_method.get? && ((defined?(helpers) && helpers) || options[:authenticity_token])
|
152
162
|
end
|
153
163
|
|
154
164
|
# Retrieves the authenticity token.
|
@@ -171,22 +181,11 @@ module Phlexi
|
|
171
181
|
#
|
172
182
|
# @return [String, nil] The appropriate form method
|
173
183
|
def object_form_method
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
#
|
180
|
-
# @return [Class] The namespace class
|
181
|
-
def namespace_klass
|
182
|
-
@namespace_klass ||= options.delete(:namespace_klass) || Structure::Namespace
|
183
|
-
end
|
184
|
-
|
185
|
-
# Retrieves the builder class.
|
186
|
-
#
|
187
|
-
# @return [Class] The builder class
|
188
|
-
def builder_klass
|
189
|
-
@builder_klass ||= options.delete(:builder_klass) || Structure::FieldBuilder
|
184
|
+
if object.respond_to?(:persisted?)
|
185
|
+
object.persisted? ? "patch" : "post"
|
186
|
+
elsif object.present?
|
187
|
+
"post"
|
188
|
+
end
|
190
189
|
end
|
191
190
|
|
192
191
|
# Renders the hidden method field for non-standard HTTP methods.
|
@@ -215,12 +214,12 @@ module Phlexi
|
|
215
214
|
#
|
216
215
|
# @return [Hash] The form attributes
|
217
216
|
def form_attributes
|
218
|
-
{
|
219
|
-
|
220
|
-
method: standardized_form_method,
|
217
|
+
mix({
|
218
|
+
id: @namespace.dom_id,
|
221
219
|
class: form_class,
|
222
|
-
|
223
|
-
|
220
|
+
action: form_action,
|
221
|
+
method: standardized_form_method
|
222
|
+
}, attributes)
|
224
223
|
end
|
225
224
|
|
226
225
|
# Renders the authenticity token if required.
|
@@ -229,6 +228,16 @@ module Phlexi
|
|
229
228
|
def render_authenticity_token
|
230
229
|
authenticity_token_field
|
231
230
|
end
|
231
|
+
|
232
|
+
private
|
233
|
+
|
234
|
+
def default_namespace_klass
|
235
|
+
self.class::Namespace
|
236
|
+
end
|
237
|
+
|
238
|
+
def default_builder_klass
|
239
|
+
self.class::FieldBuilder
|
240
|
+
end
|
232
241
|
end
|
233
242
|
end
|
234
243
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module Phlexi
|
4
4
|
module Form
|
5
5
|
module Components
|
6
|
-
class Base <
|
6
|
+
class Base < COMPONENT_BASE
|
7
7
|
attr_reader :field, :attributes
|
8
8
|
|
9
9
|
def initialize(field, **attributes)
|
@@ -11,21 +11,27 @@ module Phlexi
|
|
11
11
|
@attributes = attributes
|
12
12
|
|
13
13
|
build_attributes
|
14
|
+
append_attribute_classes
|
14
15
|
end
|
15
16
|
|
16
17
|
protected
|
17
18
|
|
18
19
|
def build_attributes
|
19
|
-
attributes[:id]
|
20
|
-
|
20
|
+
attributes.fetch(:id) { attributes[:id] = "#{field.dom.id}_#{component_name}" }
|
21
|
+
end
|
22
|
+
|
23
|
+
def append_attribute_classes
|
24
|
+
return if attributes[:class] == false
|
25
|
+
|
26
|
+
default_classes = tokens(
|
21
27
|
component_name,
|
22
|
-
attributes[:
|
23
|
-
-> {
|
24
|
-
-> { !field.required? } => "optional",
|
28
|
+
-> { attributes[:required] } => "required",
|
29
|
+
-> { !attributes[:required] } => "optional",
|
25
30
|
-> { field.has_errors? } => "invalid",
|
26
|
-
-> {
|
27
|
-
-> {
|
31
|
+
-> { attributes[:readonly] } => "readonly",
|
32
|
+
-> { attributes[:disabled] } => "disabled"
|
28
33
|
)
|
34
|
+
attributes[:class] = tokens(default_classes, attributes[:class])
|
29
35
|
end
|
30
36
|
|
31
37
|
def component_name
|
@@ -4,26 +4,40 @@ module Phlexi
|
|
4
4
|
module Form
|
5
5
|
module Components
|
6
6
|
class CollectionCheckboxes < Base
|
7
|
+
include Concerns::HandlesInput
|
8
|
+
include Concerns::HandlesArrayInput
|
7
9
|
include Concerns::HasOptions
|
8
10
|
|
9
11
|
def view_template
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
12
|
+
div(**attributes.slice(:id, :class)) do
|
13
|
+
field.repeated(option_mapper.values) do |builder|
|
14
|
+
render builder.hidden_field_tag if builder.index == 0
|
15
|
+
|
16
|
+
field = builder.field(
|
17
|
+
label: option_mapper[builder.key],
|
18
|
+
# We set the attributes here so they are applied to all input components even if the user decides to use a block
|
19
|
+
input_attributes: {
|
20
|
+
checked_value: builder.key,
|
21
|
+
include_hidden: false,
|
22
|
+
checked: selected?(builder.key)
|
23
|
+
}
|
24
|
+
)
|
25
|
+
if block_given?
|
26
|
+
yield field
|
27
|
+
else
|
28
|
+
render field.checkbox_tag
|
29
|
+
render field.label_tag
|
30
|
+
end
|
24
31
|
end
|
25
32
|
end
|
26
33
|
end
|
34
|
+
|
35
|
+
protected
|
36
|
+
|
37
|
+
def build_attributes
|
38
|
+
super
|
39
|
+
attributes[:multiple] = true
|
40
|
+
end
|
27
41
|
end
|
28
42
|
end
|
29
43
|
end
|
@@ -4,22 +4,28 @@ module Phlexi
|
|
4
4
|
module Form
|
5
5
|
module Components
|
6
6
|
class CollectionRadioButtons < Base
|
7
|
+
include Concerns::HandlesInput
|
7
8
|
include Concerns::HasOptions
|
8
9
|
|
9
10
|
def view_template
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
11
|
+
div(**attributes.slice(:id, :class)) do
|
12
|
+
field.repeated(option_mapper.values) do |builder|
|
13
|
+
render builder.hidden_field_tag if builder.index == 0
|
14
|
+
|
15
|
+
field = builder.field(
|
16
|
+
label: option_mapper[builder.key],
|
17
|
+
# We set the attributes here so they are applied to all input components even if the user decides to use a block
|
18
|
+
input_attributes: {
|
19
|
+
checked_value: builder.key,
|
20
|
+
checked: selected?(builder.key)
|
21
|
+
}
|
22
|
+
)
|
23
|
+
if block_given?
|
24
|
+
yield field
|
25
|
+
else
|
26
|
+
render field.radio_button_tag
|
27
|
+
render field.label_tag
|
28
|
+
end
|
23
29
|
end
|
24
30
|
end
|
25
31
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Phlexi
|
4
|
+
module Form
|
5
|
+
module Components
|
6
|
+
module Concerns
|
7
|
+
module ExtractsInput
|
8
|
+
# Collects parameters matching the input field's param key.
|
9
|
+
#
|
10
|
+
# @param params [Hash] the parameters to collect from.
|
11
|
+
# @return [Hash] the collected parameters.
|
12
|
+
def extract_input(params)
|
13
|
+
# # Handles multi parameter attributes
|
14
|
+
# # https://www.cookieshq.co.uk/posts/rails-spelunking-date-select
|
15
|
+
# # https://www.cookieshq.co.uk/posts/multiparameter-attributes
|
16
|
+
|
17
|
+
# # Matches
|
18
|
+
# # - parameter
|
19
|
+
# # - parameter(1)
|
20
|
+
# # - parameter(2)
|
21
|
+
# # - parameter(1i)
|
22
|
+
# # - parameter(2f)
|
23
|
+
# regex = /^#{param}(\(\d+[if]?\))?$/
|
24
|
+
# keys = params.select { |key, _| regex.match?(key) }.keys
|
25
|
+
# params.slice(*keys)
|
26
|
+
|
27
|
+
params ||= {}
|
28
|
+
{input_param => normalize_input(params[field.key])}
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
def build_attributes
|
34
|
+
super
|
35
|
+
@input_param = attributes.delete(:input_param) || field.key
|
36
|
+
end
|
37
|
+
|
38
|
+
def input_param
|
39
|
+
@input_param
|
40
|
+
end
|
41
|
+
|
42
|
+
def normalize_input(input_value)
|
43
|
+
normalize_simple_input(input_value)
|
44
|
+
end
|
45
|
+
|
46
|
+
def normalize_simple_input(input_value)
|
47
|
+
input_value.to_s.presence
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|