Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 844 lines (613 sloc) 33.102 kb
7fa300f Jeremy Evans Initial WIP
authored
1 = Forme
2
3 Forme is a HTML forms library for ruby with the following goals:
4
7289221 Jeremy Evans Add RDoc documentation
authored
5 1. Have no external dependencies
6 2. Have a simple API
7 3. Support forms both with and without related objects
8 4. Allow compiling down to different types of output
7fa300f Jeremy Evans Initial WIP
authored
9
3999463 Further suggested documentation edits
Dave Howell authored
10 = Introduction
11
12 Forme is designed to make creating HTML forms easier. Flexibility and
13 simplicity are primary objectives. The basic usage involves creating
14 a <tt>Forme::Form</tt> instance, and calling +input+ and +tag+ methods
15 to return html strings for widgets, but it could also be used for
16 serializing to other formats, or even as a DSL for a GUI application.
760d4c4 Jeremy Evans Minor cleanup to previous commit
authored
17
3999463 Further suggested documentation edits
Dave Howell authored
18 In order to be flexible, Forme stores tags in abstract form until
19 output is requested. There are two separate abstract <i>forms</i> that Forme
20 uses. One is <tt>Forme::Input</tt>, and the other is <tt>Forme::Tag</tt>.
21 <tt>Forme::Input</tt> is a high level abstract form, while <tt>Forme::Tag</tt>
22 is a low level abstract form.
760d4c4 Jeremy Evans Minor cleanup to previous commit
authored
23
3999463 Further suggested documentation edits
Dave Howell authored
24 The difference between <tt>Forme::Input</tt> and <tt>Forme::Tag</tt>
25 is that <tt>Forme::Tag</tt> directly represents the underlying html
26 tag, containing a type, optional attributes, and children, while the
27 <tt>Forme::Input</tt> is more abstract and attempts to be user friendly.
28 For example, these both compile by default to the same select tag:
29
30 f.input(:select, :options=>[['foo', 1]])
31 # or
32 f.tag(:select, {}, [f.tag(:option, {:value=>1}, ['foo'])])
760d4c4 Jeremy Evans Minor cleanup to previous commit
authored
33
3999463 Further suggested documentation edits
Dave Howell authored
34 The processing of high level <tt>Forme::Input</tt>s into raw html
35 data is broken down to the following steps (called transformers):
760d4c4 Jeremy Evans Minor cleanup to previous commit
authored
36
f0a1076 Jeremy Evans Fix minor issues in the RDoc
authored
37 +Formatter+ :: converts a <tt>Forme::Input</tt> instance into a
38 <tt>Forme::Tag</tt> instance (or array of them).
39 +ErrorHandler+ :: If the <tt>Forme::Input</tt> instance has a error,
40 takes the formatted tag and marks it as having the error.
41 +Labeler+ :: If the <tt>Forme::Input</tt> instance has a label,
42 takes the formatted output and labels it.
43 +Wrapper+ :: Takes the output of the formatter, labeler, and
44 error_handler transformers, and wraps it in another tag (or just
45 returns it unmodified).
46 +Serializer+ :: converts a <tt>Forme::Tag</tt> instance into an
47 html string.
760d4c4 Jeremy Evans Minor cleanup to previous commit
authored
48
3999463 Further suggested documentation edits
Dave Howell authored
49 Technically, only the +Serializer+ is necessary. The +input+
50 and +tag+ methods return +Input+ and +Tag+ objects. These objects
51 both have +to_s+ defined to call the appropriate +Serializer+ with
52 themselves. The +Serializer+ calls the appropriate +Formatter+ if
53 it encounters an +Input+ instance, and attempts to serialize the
54 output of that (which is usually a +Tag+ instance). It is up to
55 the +Formatter+ to call the +Labeler+ and/or +ErrorHandler+ (if
56 necessary) and the +Wrapper+.
57
58 There is also an +InputsWrapper+ transformer, that is called by
59 <tt>Forme::Form#inputs</tt>. It's used to wrap up a group of
60 related options (in a fieldset by default).
760d4c4 Jeremy Evans Minor cleanup to previous commit
authored
61
3999463 Further suggested documentation edits
Dave Howell authored
62 The <tt>Forme::Form</tt> object takes the 6 transformers as options (:formatter,
63 :labeler, :error_handler, :wrapper, :inputs_wrapper, and :serializer), all of which
64 should be objects responding to +call+ (so you can use +Proc+s) or be symbols
65 registered with the library using <tt>Forme.register_transformer</tt>:
760d4c4 Jeremy Evans Minor cleanup to previous commit
authored
66
3999463 Further suggested documentation edits
Dave Howell authored
67 Forme.register_transformer(:wrapper, :p){|t| t.tag(:p, {}, t)}
760d4c4 Jeremy Evans Minor cleanup to previous commit
authored
68
3999463 Further suggested documentation edits
Dave Howell authored
69 Most of the transformers can be overridden on a per instance basis by
70 passing the appopriate option to +input+ or +inputs+:
760d4c4 Jeremy Evans Minor cleanup to previous commit
authored
71
3999463 Further suggested documentation edits
Dave Howell authored
72 f.input(:name, :wrapper=>:p)
73
74
c426b39 Jeremy Evans Add installation instructions to README
authored
75 = Installation
76
c4f6730 Jeremy Evans Add links to IRC channel, Google Group, and bug tracker
authored
77 gem install forme
c426b39 Jeremy Evans Add installation instructions to README
authored
78
c4f6730 Jeremy Evans Add links to IRC channel, Google Group, and bug tracker
authored
79 = Links
9a3f378 Jeremy Evans Update the README
authored
80
c4f6730 Jeremy Evans Add links to IRC channel, Google Group, and bug tracker
authored
81 Demo Site :: http://forme-demo.jeremyevans.net
82 RDoc :: http://forme.jeremyevans.net
83 Source :: https://github.com/jeremyevans/forme
84 IRC :: irc://irc.freenode.net/forme
85 Google Group :: https://groups.google.com/forum/#!forum/ruby-forme
86 Bug Tracker :: https://github.com/jeremyevans/forme/issues
9a3f378 Jeremy Evans Update the README
authored
87
8375d6b Jeremy Evans Massive refactoring, completely new API
authored
88 = Basic Usage
7fa300f Jeremy Evans Initial WIP
authored
89
9a3f378 Jeremy Evans Update the README
authored
90 Without an object, Forme is a simple form builder:
8375d6b Jeremy Evans Massive refactoring, completely new API
authored
91
92 f = Forme::Form.new
b954ab7 Jeremy Evans Update README
authored
93 f.open(:action=>'/foo', :method=>:post) # '<form action="/foo" method="post">'
8375d6b Jeremy Evans Massive refactoring, completely new API
authored
94 f.input(:textarea, :value=>'foo', :name=>'bar') # '<textarea name="bar">foo</textarea>'
95 f.input(:text, :value=>'foo', :name=>'bar') # '<input name="bar" type="text" value="foo"/>'
96 f.close # '</form>'
97
9312369 Jeremy Evans Update documentation in lib/forme.rb
authored
98 With an object, <tt>Form#input</tt> calls +forme_input+ on the obj with the form, field, and options, which
99 should return a <tt>Forme::Input</tt> or <tt>Forme::Tag</tt> instance. Also, in <tt>Form#initialize</tt>,
100 +forme_config+ is called on object with the form if the object responds to it, allowing customization of
101 the entire form based on the object.
8375d6b Jeremy Evans Massive refactoring, completely new API
authored
102
103 f = Forme::Form.new(obj)
104 f.input(:field) # '<input id="obj_field" name="obj[field]" type="text" value="foo"/>'
105
889b27b Jeremy Evans Handle case where object does not respond to forme_input
authored
106 If the object doesn't respond to +forme_input+, it falls back to creating text fields
107 with the name and id set to the field name and the value set by calling the given method
2bb7784 Jeremy Evans Add a lot more information to the README
authored
108 on the object (or using #[] if the object is a hash).
889b27b Jeremy Evans Handle case where object does not respond to forme_input
authored
109
110 f = Forme::Form.new([:foo])
111 f.input(:first) # '<input id="first" name="first" type="text" value="foo"/>'
112
e0177fd Jeremy Evans Add section on DSL to the README
authored
113 = DSL
114
9a3f378 Jeremy Evans Update the README
authored
115 Forme comes with a DSL:
e0177fd Jeremy Evans Add section on DSL to the README
authored
116
117 Forme.form(:action=>'/foo') do |f|
118 f.input(:text, :name=>'bar')
119 f.tag(:fieldset) do
120 f.input(:textarea, :name=>'baz')
121 end
2bb7784 Jeremy Evans Add a lot more information to the README
authored
122 f.button('Update')
e0177fd Jeremy Evans Add section on DSL to the README
authored
123 end
124 # <form action="/foo">
125 # <input name="bar" type="text"/>
126 # <fieldset>
127 # <textarea name="baz"></textarea>
128 # </fieldset>
2bb7784 Jeremy Evans Add a lot more information to the README
authored
129 # <input type="submit" value="Update"/>
e0177fd Jeremy Evans Add section on DSL to the README
authored
130 # </form>
131
9a3f378 Jeremy Evans Update the README
authored
132 You can wrap up multiple inputs with the <tt>:inputs</tt> method:
133
134 Forme.form(:action=>'/foo') do |f|
b954ab7 Jeremy Evans Update README
authored
135 f.inputs([[:text, {:name=>'bar'}], [:textarea, {:name=>'baz'}]])
9a3f378 Jeremy Evans Update the README
authored
136 end
137 # <form action="/foo">
b954ab7 Jeremy Evans Update README
authored
138 # <fieldset class="inputs">
9a3f378 Jeremy Evans Update the README
authored
139 # <input name="bar" type="text"/>
140 # <textarea name="baz"></textarea>
141 # </fieldset>
142 # </form>
143
b954ab7 Jeremy Evans Update README
authored
144 You can even do everything in a single method call:
145
146 Forme.form({:action=>'/foo'},
147 :inputs=>[[:text, {:name=>'bar'}], [:textarea, {:name=>'baz'}]])
148
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
149 = Forme::Form Creation
b4693a3 Jeremy Evans Document supported types and options in the README
authored
150
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
151 As shown above, the general way to create Forme::Form instances is via the Forme.form method.
152 This method takes up to 3 arguments, and yields the Forme::Form object to the block (if given).
153 Here are the argument styles that you can use for Forme.form.
d83598d Jeremy Evans Add documentation on form and transformer options to the README
authored
154
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
155 No args :: Creates a +Form+ object with no options and not associated
156 to an +obj+, and with no attributes in the opening tag.
157 1 hash arg :: Treated as opening form tag attributes, creating a
158 +Form+ object with no options.
159 1 non-hash arg :: Treated as the +Form+'s +obj+, with empty options
160 and no attributes in the opening tag.
161 2 hash args :: First hash is opening attributes, second hash is +Form+
162 options.
163 1 non-hash arg, 1-2 hash args :: First argument is +Form+'s obj, second is
164 opening attributes, third if provided is
165 +Form+'s options.
b4693a3 Jeremy Evans Document supported types and options in the README
authored
166
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
167 Examples:
b4693a3 Jeremy Evans Document supported types and options in the README
authored
168
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
169 # No arguments
170 Forme.form
b4693a3 Jeremy Evans Document supported types and options in the README
authored
171
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
172 # 1 hash argument (attributes)
173 Forme.form(:action=>'/foo')
b4693a3 Jeremy Evans Document supported types and options in the README
authored
174
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
175 # 1 non-hash argument (a reference object used when building the form)
176 Forme.form(Album[1])
b4693a3 Jeremy Evans Document supported types and options in the README
authored
177
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
178 # 2 hash arguments (attributes, and options)
179 Forme.form({:action=>'/foo'}, :values=>params)
b4693a3 Jeremy Evans Document supported types and options in the README
authored
180
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
181 # 1 non-hash argument, 1-2 hash arguments (ref obj, attributes, options)
182 Forme.form(Album[1], :action=>'/foo')
183 Forme.form(Album[1], {:action=>'/foo'}, :values=>params)
b4693a3 Jeremy Evans Document supported types and options in the README
authored
184
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
185 If you want a Forme::Form instance where the reference object is a Hash, then you need to pass the hash object using the :obj option:
b4693a3 Jeremy Evans Document supported types and options in the README
authored
186
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
187 Forme.form({:action=>'/foo'}, :obj=>{:foo=>'bar'})
b4693a3 Jeremy Evans Document supported types and options in the README
authored
188
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
189 You can also create Forme::Form objects the normal ruby way using Forme::Form#new. The
190 difference between Forme::Form#new and Forme.form is that Forme.form includes the enclosing
191 <form> tag, where Forme::Form#new does not. Because of this, Forme::Form does not accept
192 a hash of <form> tag attributes, so it has the following API:
b4693a3 Jeremy Evans Document supported types and options in the README
authored
193
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
194 # No arguments
195 Forme::Form.new
b4693a3 Jeremy Evans Document supported types and options in the README
authored
196
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
197 # 1 hash argument
198 Forme::Form.new(:values=>params)
b4693a3 Jeremy Evans Document supported types and options in the README
authored
199
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
200 # 1 non-hash argument
201 Forme::Form.new(Album[1])
b4693a3 Jeremy Evans Document supported types and options in the README
authored
202
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
203 # 1 non-hash argument, 1-2 hash arguments
204 Forme::Form.new(Album[1], :values=>params)
b4693a3 Jeremy Evans Document supported types and options in the README
authored
205
e412d14 Jeremy Evans Minor README changes (Fixes #7)
authored
206 = Forme::Form Methods
b4693a3 Jeremy Evans Document supported types and options in the README
authored
207
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
208 == form
b4693a3 Jeremy Evans Document supported types and options in the README
authored
209
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
210 If you create a Form via Forme::Forme#new, you can use the form method to create a form tag:
b4693a3 Jeremy Evans Document supported types and options in the README
authored
211
e412d14 Jeremy Evans Minor README changes (Fixes #7)
authored
212 f = Forme::Form.new
213 f.form(:action=>'/foo')
b4693a3 Jeremy Evans Document supported types and options in the README
authored
214
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
215 This is what Forme.form uses internally to create the <form> tag
b4693a3 Jeremy Evans Document supported types and options in the README
authored
216
e412d14 Jeremy Evans Minor README changes (Fixes #7)
authored
217 == input
218
219 This adds an input to the form. If the form has an associated object, and that
220 object responds to +forme_input+, calls forme_input with the argument and options:
221
222 f = Forme::Form.new(obj)
223 f.input(:field) # '<input id="obj_field" name="obj[field]" type="text" value="foo"/>'
224
225 If the form has an associated object, and that object does not respond to +forme_iuput+,
226 calls the method on the object (or uses [] if the object is a hash), and uses the result
227 as the value:
228
229 f = Forme::Form.new([:foo])
230 f.input(:first) # '<input id="first" name="first" type="text" value="foo"/>'
231
232 If the form does not have an assocaited object, uses the first argument as the input
233 type:
234
235 f = Forme::Form.new
236 f.input(:text) # '<input type="text" />'
237
238 The second argument is an options hash. See below for the supported input types and options.
239
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
240 == tag
b4693a3 Jeremy Evans Document supported types and options in the README
authored
241
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
242 This adds a tag to the form. If a block is given, yields to the block, and tags and inputs
243 inside the block are placed inside the tag. The first argument is the type of tag to create,
244 and the second argument if given should be a hash of tag attributes. This allows you to nest
245 inputs inside tags:
b4693a3 Jeremy Evans Document supported types and options in the README
authored
246
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
247 Forme.form do |f|
f0a1076 Jeremy Evans Fix minor issues in the RDoc
authored
248 f.tag(:span, :class=>"foo") do
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
249 f.input(:text)
250 end
251 end
b4693a3 Jeremy Evans Document supported types and options in the README
authored
252
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
253 Which results in a form similar to the following:
b4693a3 Jeremy Evans Document supported types and options in the README
authored
254
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
255 <form>
256 <span class="foo">
257 <input type="text"/>
258 </span>
259 </form>
b4693a3 Jeremy Evans Document supported types and options in the README
authored
260
e412d14 Jeremy Evans Minor README changes (Fixes #7)
authored
261 == inputs
262
263 This wraps multiple inputs in a tag (it uses the inputs_wrapper transformer discussed below,
264 so it uses a fieldset by default). You can give the inputs to add as an enumerable argument:
265
266 f.inputs([:textarea, [:text, :value=>'a']])
267 # <fieldset>
268 # <textarea></textarea>
269 # <input type="text" value="a"/>
270 # </fieldset>
271
272 You can also provide a block:
273
274 f.inputs([:textarea]) do
275 f.input(:text, :value=>'a')
276 end
277
278 Any options given are passed to the inputs_wrapper (so you can use options such as :legend
279 to set a legend for the fieldset), and also to the the with_opts (so you can use options
280 such as :wrapper to modify the default wrapper transformer for inputs inside the block).
281 There is also one option specific to the inputs method:
282
283 :nested_inputs_wrapper :: Sets the default inputs_wrapper to use for calls to inputs inside
284 the block. The reason for this option is that :inputs_wrapper
285 option affects the current call to inputs, so if you want to
286 use a different inputs_wrapper for nested calls, you need this option.
287
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
288 == button
b4693a3 Jeremy Evans Document supported types and options in the README
authored
289
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
290 This adds a submit input to the form:
b4693a3 Jeremy Evans Document supported types and options in the README
authored
291
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
292 f.button
293 # <input type="submit"/>
b4693a3 Jeremy Evans Document supported types and options in the README
authored
294
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
295 It can be called with a string to provide a value for the button:
b4693a3 Jeremy Evans Document supported types and options in the README
authored
296
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
297 f.button('Search')
298 # <input type="submit" value="Search"/>
d83598d Jeremy Evans Add documentation on form and transformer options to the README
authored
299
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
300 It can be called with a hash to provide options for the submit input:
d83598d Jeremy Evans Add documentation on form and transformer options to the README
authored
301
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
302 f.button(:value=>'Search', :class=>'btn')
303 # <input class="btn" type="submit" value="Search"/>
2bb7784 Jeremy Evans Add a lot more information to the README
authored
304
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
305 == with_opts
2bb7784 Jeremy Evans Add a lot more information to the README
authored
306
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
307 This requires a block, and modifies the Form's options inside the block,
308 restoring the options when the block returns:
d83598d Jeremy Evans Add documentation on form and transformer options to the README
authored
309
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
310 f.input(:text)
311 # <input type="text"/>
312 f.with_opts(:wrapper=>:li) do
313 f.input(:text)
314 end
315 # <li><input type="text"/></li>
d83598d Jeremy Evans Add documentation on form and transformer options to the README
authored
316
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
317 This supports most options you can provide to the Form, but not all.
d83598d Jeremy Evans Add documentation on form and transformer options to the README
authored
318
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
319 == with_obj
d83598d Jeremy Evans Add documentation on form and transformer options to the README
authored
320
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
321 This uses with_opts to change the Form's object temporarily, but it
322 yields the object to the block, and also supports appending to the
323 existing namespaces:
898eb18 Jeremy Evans Add some information on the internal design, transformer purpose, and bu...
authored
324
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
325 Forme.form([:foo], :namespace=>'a') do |f|
326 f.input(:first)
327 # <input id="a_first" name="a[first]" type="text" value="foo"/>
328 f.with_obj(['foobar'], 'b') do |o|
329 f.input(:first, :size=>o.first.size)
330 # <input id="a_b_first" name="a[b][first]" size="6" type="text" value="foobar"/>
331 end
332 end
8375d6b Jeremy Evans Massive refactoring, completely new API
authored
333
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
334 == each_obj
898eb18 Jeremy Evans Add some information on the internal design, transformer purpose, and bu...
authored
335
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
336 This allows you to provide an object-yielding enumerable. Forme will call with_obj with
337 each object in the enumerable. It yields each object as well as the index of the
338 object in the enumerable, and includes the index in the namespace:
898eb18 Jeremy Evans Add some information on the internal design, transformer purpose, and bu...
authored
339
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
340 objectlist = ['foobar', ['good']]
341 Forme.form([:foo], :namespace=>'a') do |f|
342 f.each_obj(objectlist, 'b') do |o, i|
343 f.input(:first, :size=>10+i)
344 end
345 # <input id="a_b_0_first" name="a[b][0][first]" size="10" type="text" value="foobar"/>
346 # <input id="a_b_1_first" name="a[b][1][first]" size="11" type="text" value="good"/>
347 end
898eb18 Jeremy Evans Add some information on the internal design, transformer purpose, and bu...
authored
348
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
349 = Sequel Support
898eb18 Jeremy Evans Add some information on the internal design, transformer purpose, and bu...
authored
350
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
351 Forme ships with a Sequel plugin (use <tt>Sequel::Model.plugin :forme</tt> to enable), that makes
352 Sequel::Model instances support the +forme_config+ and +forme_input+ methods and return customized inputs.
898eb18 Jeremy Evans Add some information on the internal design, transformer purpose, and bu...
authored
353
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
354 == Basics
898eb18 Jeremy Evans Add some information on the internal design, transformer purpose, and bu...
authored
355
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
356 The Sequel support handles inputs based on database columns, and automatically handles labels and errors.
898eb18 Jeremy Evans Add some information on the internal design, transformer purpose, and bu...
authored
357
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
358 Forme.form(Album[1], :action=>'/foo') do |f|
359 f.input :name
360 f.input :copies_sold
361 end
898eb18 Jeremy Evans Add some information on the internal design, transformer purpose, and bu...
authored
362
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
363 This will create a form similar to:
898eb18 Jeremy Evans Add some information on the internal design, transformer purpose, and bu...
authored
364
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
365 <form action="/foo" method="post">
366 <label>Name: <input id="album_name" name="album[name]" type="text" value="Rising Force"/></label>
367 <label>Copies Sold: <input id="album_copies_sold" name="album[copies_sold]" type="number" value="100000"/></label>
368 </form>
898eb18 Jeremy Evans Add some information on the internal design, transformer purpose, and bu...
authored
369
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
370 The Forme Sequel plugin also integerates with Sequel's validation reflection support with the
371 +validation_class_methods+ plugin that ships with Sequel. It will add +pattern+ and +maxlength+ attributes
372 based on the format, numericality, and length validations.
b954ab7 Jeremy Evans Update README
authored
373
2bb7784 Jeremy Evans Add a lot more information to the README
authored
374 == specialized input options
375
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
376 In addition to the default Forme options, the Sequel support includes, for specific column types,
377 these additional options to the #input method:
378 .
2bb7784 Jeremy Evans Add a lot more information to the README
authored
379
380 === boolean
381
382 :as :: Can be set to :select, :radio, or :checkbox. :select will use a select input with three
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
383 options, a blank option, a true option, and a false option. :radio will use two radio
2bb7784 Jeremy Evans Add a lot more information to the README
authored
384 inputs, one for true and one for false. :checkbox will use a single checkbox input.
385 By default, uses :select if NULL values are allowed and the option is not required, and
386 :checkbox otherwise.
387 :false_label :: The value to use for the false label, 'No' by default.
388 :false_value :: The value to use for the false input, 'f' by default.
389 :true_label :: The value to use for the true label, 'Yes' by default.
390 :true_value :: The value to use for the true input, 't' by default.
391
392 == string
393
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
394 :as :: Can be set to :textarea to use a textarea input. You can use the usual attributes hash or a stylesheet to
d90d776 Jeremy Evans Fix rdoc formatting in README
authored
395 control the size of the textarea.
2bb7784 Jeremy Evans Add a lot more information to the README
authored
396
397 == associations
398
399 The Sequel support also handles associations, allowing you to change which objects are associated
400 to the current object.
401
402 Forme.form(Album[1], :action=>'/foo') do |f|
403 f.input :name
404 f.input :artist
405 f.input :tags, :as=>:checkbox
406 end
407
408 This will create a form similar to:
409
410 <form action="/foo" method="post">
411 <label>Name: <input id="album_name" name="album[name]" type="text" value="Blue Hawaii"/></label>
412 <label>Artist: <select id="album_artist_id" name="album[artist_id]">
413 <option selected="selected" value="1">Elvis Presley</option>
414 <option value="2">The Beatles</option>
415 <option value="3">The Monkeys</option>
416 </select></label>
417 <span class="label">Tags:
418 <label><input checked="checked" id="album_tag_pks_1" name="album[tag_pks][]" type="checkbox" value="1"/> Rock and Roll</label>
419 <label><input id="album_tag_pks_2" name="album[tag_pks][]" type="checkbox" value="2"/> Blues</label>
420 <label><input id="album_tag_pks_3" name="album[tag_pks][]" type="checkbox" value="3"/> Country</label>
421 </span>
422 </form>
423
424 For one_to_many and many_to_many associations, you will probably want to use the
425 +association_pks+ plugin that ships with Sequel.
426
c1181b8 Jeremy Evans Update README for recent feature additions
authored
427 This supports the pg_array_to_many association type that comes with Sequel's
428 +pg_array_association+ plugin.
429
2bb7784 Jeremy Evans Add a lot more information to the README
authored
430 association input options:
431
432 :as :: For many_to_one associations, set to :radio to use a series of radio buttons instead
c1181b8 Jeremy Evans Update README for recent feature additions
authored
433 a select input. For one_to_many, many_to_many, and pg_array_to_many associations, set
434 to :checkbox to use a series of checkboxes instead of a multiple select input.
2bb7784 Jeremy Evans Add a lot more information to the README
authored
435 :dataset :: If a Dataset, uses the dataset to retrieve the options. If a Proc or Method,
436 calls the proc or method with the default dataset, and should return a modified
437 dataset to use.
438 :options :: Specify the options to use for the input(s), instead of querying the database.
439 :name_method :: If a String or Symbol, treats it as a method name and calls it on each object
440 returned by the dataset to get the text to use for the option. If not given,
441 tries the following method names in order: :forme_name, :name, :title, :number.
442 If given and not a String or Symbol, a callable object is assumed, and the value
443 is called with each object and should return the text to use for the option.
444
445 == subform
446
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
447 The Sequel support includes a method called subform, which can handle nested_attributes:
2bb7784 Jeremy Evans Add a lot more information to the README
authored
448
449 Forme.form(Album[1], :action=>'/foo') do |f|
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
450
2bb7784 Jeremy Evans Add a lot more information to the README
authored
451 f.input :name
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
452
2bb7784 Jeremy Evans Add a lot more information to the README
authored
453 f.subform :artist do
454 f.input :name
455 end
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
456
2bb7784 Jeremy Evans Add a lot more information to the README
authored
457 f.subform :tracks do
458 f.input :number
459 f.input :name
460 end
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
461
2bb7784 Jeremy Evans Add a lot more information to the README
authored
462 end
463
464 This adds an input for editing the artist's name after the album's inputs, as well as
465 inputs for editing the number and name for all of the tracks in the album, creating a
466 form similar to:
467
468 <form action="/foo" method="post">
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
469
2bb7784 Jeremy Evans Add a lot more information to the README
authored
470 <label>Name: <input id="album_name" name="album[name]" type="text" value="Blue Hawaii"/></label>
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
471
2bb7784 Jeremy Evans Add a lot more information to the README
authored
472 <input id="album_artist_attributes_id" name="album[artist_attributes][id]" type="hidden" value="1"/>
473 <fieldset class="inputs"><legend>Artist</legend>
474 <label>Name: <input id="album_artist_attributes_name" name="album[artist_attributes][name]" type="text" value="Elvis Presley"/></label>
475 </fieldset>
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
476
2bb7784 Jeremy Evans Add a lot more information to the README
authored
477 <input id="album_tracks_attributes_0_id" name="album[tracks_attributes][0][id]" type="hidden" value="1"/>
478 <fieldset class="inputs"><legend>Track #1</legend>
479 <label>Number: <input id="album_tracks_attributes_0_number" name="album[tracks_attributes][0][number]" type="number" value="1"/></label>
480 <label>Name: <input id="album_tracks_attributes_0_name" name="album[tracks_attributes][0][name]" type="text" value="Blue Hawaii"/></label>
481 </fieldset>
482 <input id="album_tracks_attributes_1_id" name="album[tracks_attributes][1][id]" type="hidden" value="2"/>
483 <fieldset class="inputs"><legend>Track #2</legend>
484 <label>Number: <input id="album_tracks_attributes_1_number" name="album[tracks_attributes][1][number]" type="number" value="2"/></label>
485 <label>Name: <input id="album_tracks_attributes_1_name" name="album[tracks_attributes][1][name]" type="text" value="Almost Always True"/></label>
486 </fieldset>
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
487
2bb7784 Jeremy Evans Add a lot more information to the README
authored
488 </form>
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
489
490 <em>Note: blank lines added for clarity; they would not appear in the actual output</em>
2bb7784 Jeremy Evans Add a lot more information to the README
authored
491
492 subform options:
493
494 :inputs :: Automatically call +inputs+ with the given values. Using
495 this, it is not required to pass a block to the method,
496 though it will still work if you do.
497 :legend :: Overrides the default :legend used (which is based on the
498 association name). You can also use a proc as the value,
499 which will called with each associated object (and the position
500 in the associated object already for *_to_many associations),
501 and should return the legend string to use for that object.
502 :grid :: Sets up a table with one row per associated object, and
503 one column per field.
504 :labels :: When using the :grid option, override the labels that would
505 be created via the :inputs option. If you are not providing
506 an :inputs option or are using a block with additional inputs,
507 you should specify this option.
c1181b8 Jeremy Evans Update README for recent feature additions
authored
508 :inputs_opts :: When using the :grid option, this allows you to specify options
509 to pass to the table InputsWrapper.
2bb7784 Jeremy Evans Add a lot more information to the README
authored
510
f0a1076 Jeremy Evans Fix minor issues in the RDoc
authored
511 = ERB Support
a5d0c33 Jeremy Evans Update the README, mentioning the RDoc documentation, and Sequel and Sin...
authored
512
f0a1076 Jeremy Evans Fix minor issues in the RDoc
authored
513 Forme ships with a ERB extension that you can get by <tt>require "forme/erb"</tt> and using
514 <tt>including Forme::ERB::Helper</tt>. This is tested to support ERB templates in both the
515 Sinatra and Roda web frameworks. It allows you to use the following API in your erb
516 templates:
a5d0c33 Jeremy Evans Update the README, mentioning the RDoc documentation, and Sequel and Sin...
authored
517
518 <% form(@obj, :action=>'/foo') do |f| %>
519 <%= f.input(:field) %>
520 <% f.tag(:fieldset) do %>
521 <%= f.input(:field_two) %>
570c0c6 Jeremy Evans Fix some spacing issues in code examples in the README
authored
522 <% end %>
523 <% end %>
524
932a427 Jeremy Evans Add note to README about the default ERB outvar
authored
525 In order to this to work transparently, the ERB outvar needs to be <tt>@_out_buf</tt>. If that
526 is not the case, use the :output option to +form+ to specify the outvar.
527
bd952f2 Jeremy Evans Add Rails integration
authored
528 = Rails Support
0a7084f Jeremy Evans Update CHANGELOG, README, and spec for last commit
authored
529
bd952f2 Jeremy Evans Add Rails integration
authored
530 Forme ships with a Rails extension that you can get by <tt>require "forme/rails"</tt> and using
33fe101 tomclose Fix typo in Rails support instructions
tomclose authored
531 <tt>helper Forme::Rails::ERB</tt> in your controller. If allows you to use the following API
bd952f2 Jeremy Evans Add Rails integration
authored
532 in your Rails forms:
0a7084f Jeremy Evans Update CHANGELOG, README, and spec for last commit
authored
533
bd952f2 Jeremy Evans Add Rails integration
authored
534 <%= forme(@obj, :action=>'/foo') do |f| %>
535 <%= f.input(:field) %>
536 <%= f.tag(:fieldset) do %>
537 <%= f.input(:field_two) %>
538 <% end %>
539 <% end %>
540
2bb7784 Jeremy Evans Add a lot more information to the README
authored
541 This has been tested on Rails 3.2-4.1, but should hopefully work on Rails 3.0+.
b954ab7 Jeremy Evans Update README
authored
542
e412d14 Jeremy Evans Minor README changes (Fixes #7)
authored
543 = Input Types and Options
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
544
545 These are the types and options supported by Forme::Input objects, usually
546 created via Forme::Form#input:
547
548 == General Options
549
550 These options are supported by all of the input types:
551
552 :attr :: The attributes hash to use for the given tag, takes precedence over
553 other options that set attributes.
554 :autofocus :: Set the autofocus attribute if true
555 :class :: A class to use. Unlike other options, this is combined with the
556 classes set in the :attr hash.
557 :data :: A hash of data-* attributes for the resulting tag. Keys in this hash
558 will have attributes created with data- prepended to the attribute name.
559 :disabled :: Set the disabled attribute if true
560 :error :: Set an error message, invoking the error_handler
561 :error_handler :: Set a custom error_handler, overriding the form's default
562 :id :: The id attribute to use
563 :key :: The base to use for the name and id attributes, based on the current
564 namespace for the form.
565 :label :: Set a label, invoking the labeler
566 :labeler :: Set a custom labeler, overriding the form's default
567 :name :: The name attribute to use
568 :placeholder :: The placeholder attribute to use
569 :required :: Set the required attribute if true
570 :value :: The value attribute to use for input tags, the content of the textarea
571 for textarea tags, or the selected option(s) for select tags.
572 :wrapper :: Set a custom wrapper, overriding the form's default
573
574 == Input Types
575
576 === :checkbox
577
578 Creates an input tag with type checkbox, as well as a hidden input tag. Options:
579
580 :checked :: Mark the checkbox as checked.
581 :hidden_value :: The value to use for the hidden input tag.
582 :no_hidden :: Don't create a hidden input tag.
583
584 === :radio
585
586 Creates an input tag with type radio. Options:
587
588 :checked :: Mark the radio button as checked.
589
590 === :date
591
592 By default, creates an input tag with type date. With the :as=>:select option, creates
593 3 select boxes, one for the year, month, and day. Options:
594
595 :as :: When value is :select, uses 3 select boxes.
596
597 === :datetime
598
599 By default, creates an input tag with type datetime. With the :as=>:select option, creates
600 6 select boxes, one for the year, month, day, hour, minute, and second. Options:
601
602 :as :: When value is :select, uses 6 select boxes.
603
604 === :select
605
606 Creates a select tag, containing option tags specified by the :options option. Options:
607
608 :add_blank :: Add a blank option if true. If the value is a string,
609 use it as the text content of the blank option. The default value can be
610 set with Forme.default_add_blank_prompt, and defaults to the empty string.
611 :multiple :: Creates a multiple select box.
612 :options :: an array of options used for creating option tags.
613 If the :text_method and :value_method are not given and the entry is an
614 array, uses the first entry of the array as the text of the option, and
615 the second entry of the array as the value of the option.
616 :selected :: The value that should be selected. Any options that are equal to
617 this value (or included in this value if a multiple select box),
618 are set to selected.
1a478b7 Jeremy Evans Support :size option for select inputs
authored
619 :size :: Uses the size attribute on the tag
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
620 :text_method :: If set, each entry in the array has this option called on
621 it to get the text of the object.
622 :value :: Same as :selected, but has lower priority.
623 :value_method :: If set (and :text_method is set), each entry in the array
624 has this method called on it to get the value of the option.
625
626 === :checkboxset
627
628 Creates a set of checkbox inputs all using the same name. Supports the same options
629 as the select type, except that the :multiple option is assumed to be true.
630
631 === :radioset
632
633 Creates a set of radio buttons all using the same name. Supports the same options
634 as the select type.
635
636 === :textarea
637
638 Creates a textarea tag. Options:
639
640 :cols :: The number of columns in the text area.
641 :rows :: The number of rows in the text area.
642
643 == all others
644
645 Creates an input tag with the given type. This makes it easy to use inputs such
646 as text and password, as well as newer HTML5 inputs such as number or email. Options:
647
648 :size :: Uses the size attribute on the tag
649 :maxlength :: Use the maxlength attribute on the tag
650
651 == Form options
652
653 These are the options supported by Forme::Form object, mostly used to set
654 the defaults for Inputs created via the form:
655
656 :config :: The configuration to use, which automatically sets defaults
657 for the transformers to use.
658 :error_handler :: Sets the default error_handler for the form's inputs
659 :formatter :: Sets the default formatter for the form's inputs
660 :hidden_tags :: Sets the hidden tags to automatically add to this form, see below.
661 :input_defaults :: Sets the default options for each input type. This should
662 be a hash with input type keys, where the values are the
663 hash of default options to use for the input type.
664 :inputs_wrapper :: Sets the default inputs_wrapper for the form
665 :labeler :: Sets the default labeler for the form's inputs
666 :namespace :: Sets the default namespace(s) to use for the form. Namespacing
667 will automatically create namespaced name and id attributes for
668 inputs that use the :key option.
669 :obj :: Sets the default +obj+ for the form's inputs.
670 :serializer :: Sets the serializer for the form
671 :values :: The values from a previous form submission, used to set default
672 values for inputs when the inputs use the :key option.
673 :wrapper :: Sets the default wrapper for the form's inputs
674
675 For forms created by Forme.form, the following options are supported:
676
677 :inputs :: An array of inputs to create inside the form, before yielding
678 to the block.
679 :button :: A button to add to the form, after yielding to the block.
680
681 === :hidden_tags
682
683 This should be an array, where elements are one of the following types:
684
685 String, Array, Forme::Tag :: Added directly as a child of the form tag.
686 Hash :: Adds a hidden tag for each entry, with keys as the name of the hidden
687 tag and values as the value of the hidden tag.
688 Proc :: Will be called with the form tag object, and should return an instance
689 of one of the handled types (or nil to not add a tag).
690
691 = Basic Design
692
693 Internally, Forme builds an abstract syntax tree of objects that
694 represent the form. The abstract syntax tree goes through a
695 series of transformations that convert it from high level
696 abstract forms to low level abstract forms and finally to
697 strings. Here are the main classes used by the library:
698
699 <tt>Forme::Form</tt> :: main object
700 <tt>Forme::Input</tt> :: high level abstract tag (a single +Input+ could represent a select box with a bunch of options)
701 <tt>Forme::Tag</tt> :: low level abstract tag representing an html tag (there would be a separate +Tag+ for each option in a select box)
702
703 The group of objects that perform the transformations to
704 the abstract syntax trees are known as transformers.
705 Transformers use a functional style, and all use a +call+-based
706 API, so you can use a +Proc+ for any custom transformer.
707
708 == Transformer Types
709
710 +serializer+ :: tags input/tag, returns string
711 +formatter+ :: takes input, returns tag
712 +error_handler+ :: takes tag and input, returns version of tag with errors noted
713 +labeler+ :: takes tag and input, returns labeled version of tag
714 +wrapper+ :: takes tag and input, returns wrapped version of tag
715 +inputs_wrapper+ :: takes form, options hash, and block, wrapping block in a tag
716
717 The +serializer+ is the base of the transformations. It turns +Tag+ instances into strings. If it comes across
718 an +Input+, it calls the +formatter+ on the +Input+ to turn it into a +Tag+, and then serializes
719 that +Tag+. The +formatter+ first converts the +Input+ to a +Tag+, and then calls the
720 +error_handler+ if the <tt>:error</tt> option is set and the +labeler+ if the <tt>:label</tt>
721 option is set. Finally, it calls the +wrapper+ to wrap the resulting tag before returning it.
722
723 The +inputs_wrapper+ is called by <tt>Forme::Form#inputs</tt> and serves to wrap a bunch
724 of related inputs.
725
726 == Built-in Transformers
727
728 Forme ships with a bunch of built-in transformers that you can use:
729
730 === +serializer+
731
732 :default :: returns HTML strings
733 :html_usa :: returns HTML strings, formats dates and times in American format without timezones
734 :text :: returns plain text strings
735
736 === +formatter+
737
738 :default :: turns Inputs into Tags
739 :disabled :: disables all resulting input tags
740 :readonly :: uses +span+ tags for most values, good for printable versions of forms
741
742 === +error_handler+
743
744 :default :: modifies tag to add an error class and adds a span with the error message
745
c1181b8 Jeremy Evans Update README for recent feature additions
authored
746 This supports the following options:
747
748 :error_attr :: A hash of attributes to use for the span with the error message
749
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
750 === +labeler+
751
752 :default :: uses implicit labels, where the tag is a child of the label tag
753 :explicit :: uses explicit labels with the for attribute, where tag is a sibling of the label tag
754
755 Both of these respect the following options:
756
757 :label_position :: Can be set to :before or :after to place the label before or after the the input.
758 :label_attr :: A hash of attributes to use for the label tag
759
760 === +wrapper+
761
762 :default :: returns tag without wrapping
763 :div :: wraps tag in div tag
764 :fieldset_ol :: same as :li, but also sets +inputs_wrapper+ to :fieldset_ol
765 :li :: wraps tag in li tag
766 :ol :: same as :li, but also sets +inputs_wrapper+ to :ol
767 :p :: wraps tag in p tag
768 :span :: wraps tag in span tag
769 :table :: same as :trtd, but also sets +inputs_wrapper+ to :table
770 :td :: wraps tag in a td tag
771 :tr :: same as :td, but also sets +inputs_wrapper+ to :tr
772 :trtd :: wraps tag in a tr tag with a td for the label and a td for the tag, useful for lining up
773 inputs with the :explicit labeler without CSS
774
775 All of these except for :default respect the following options:
776
777 :wrapper_attr :: A hash of attributes to use for the wrapping tag.
778
779 === +inputs_wrapper+
780
781 :default :: uses a fieldset to wrap inputs
782 :div :: uses a div tag to wrap inputs
783 :fieldset_ol :: use both a fieldset and an ol tag to wrap inputs
784 :ol :: uses an ol tag to wrap inputs, useful with :li wrapper
785 :table :: uses a table tag to wrap inputs, useful with :trtd wrapper
786 :tr :: uses a tr tag to wrap inputs, useful with :td wrapper
787
788 All of these support the following options:
789
790 :attr :: A hash of attributes to use for the wrapping tag.
791
792 The :default, :fieldset_ol, and :table inputs_wrappers support the following options:
793
794 :legend :: A text description for the inputs, using the legend tag for fieldsets and
795 the caption tag for a table.
796 :legend_attr :: A hash of attributes for the legend/caption tag.
797
798 The :table inputs_wrapper also supports the following options:
799
800 :labels :: An array of labels, used to setup a row of table headers with the labels.
801
802 == Configurations
803
804 You can associate a group of transformers into a configuration. This allows you to
805 specify a single :config option when creating a +Form+ and have it automatically
806 set all the related transformers.
807
808 There are a few configurations supported by default:
809
810 :default :: All +default+ transformers
811 :formtastic :: +fieldset_ol+ inputs_wrapper, +li+ wrapper, +explicit+ labeler
812
813 You can register and use your own configurations easily:
814
815 Forme.register_config(:mine, :wrapper=>:li, :inputs_wrapper=>:ol, :serializer=>:html_usa)
816 Forme::Form.new(:config=>:mine)
817
818 If you want to, you can base your configuration on an existing configuration:
819
820 Forme.register_config(:yours, :base=>:mine, :inputs_wrapper=>:fieldset_ol)
821
822 You can mark a configuration as the default using:
823
824 Forme.default_config = :mine
825
e412d14 Jeremy Evans Minor README changes (Fixes #7)
authored
826 = Other Similar Projects
827
828 All of these have external dependencies:
829
830 1. Rails built-in helpers
831 2. Formtastic
832 3. simple_form
833 4. padrino-helpers
834
835 Forme's DSL draws a lot of inspiration from both Formtastic and simple_form.
836
837 = License
838
839 MIT
9737073 Suggested modifications to Readme.rdoc
Dave Howell authored
840
7fa300f Jeremy Evans Initial WIP
authored
841 = Author
842
843 Jeremy Evans <code@jeremyevans.net>
Something went wrong with that request. Please try again.