1HTML::FormFu::Manual::CUosoekrboCookn(t3r)ibuted Perl DoHcTuMmLe:n:tFaotrimoFnu::Manual::Cookbook(3)
2
3
4
6 HTML::FormFu::Manual::Cookbook - Cooking with HTML::FormFu
7
9 Miscellaneous useful recipes for use with HTML::FormFu
10
12 Some useful info for beginners.
13
14 Default search paths for config files
15 The current working directory ("cwd") (see "load_config_file" in
16 HTML::FormFu).
17
18 If you're using the "FormConfig" action attribute from
19 Catalyst::Controller::HTML::FormFu, forms should be saved in
20 "root/forms". See "SYNOPSIS" in Catalyst::Controller::HTML::FormFu and
21 "config_file_path" in Catalyst::Controller::HTML::FormFu for further
22 details.
23
24 YAML
25 Most examples given in the HTML::FormFu documentation use YAML syntax.
26 You can use any configuration file type supported by Config::Any, but
27 this author's preferred format is YAML.
28
29 A form can be populated by a config file by calling "load_config_file"
30 in HTML::FormFu with the filename as an argument. The config file is
31 converted to a perl data-structure, and then passed to "populate" in
32 HTML::FormFu.
33
34 The config file must contain a hash-ref, with the keys corresponding to
35 form method-names, and the values being the method arguments. For
36 example, the following are equivalent:
37
38 ---
39 auto_fieldset: 1
40 elements:
41 - name: foo
42 - name: bar
43
44 # the above YAML is equivalent to the following perl code
45
46 $form->auto_fieldset(1);
47
48 $form->elements([
49 { name => 'foo' },
50 { name => 'bar' },
51 ]);
52
53 When writing your config file, remember that perl hashes are unordered
54 and cannot have multiple keys with the same name.
55
56 See "load_config_file" in HTML::FormFu and "populate" in HTML::FormFu
57 for more details.
58
59 See <http://www.yaml.org/spec/> for the YAML specification.
60
62 Quick single-file prototypes
63 You can run the following script to quickly view a form's markup -
64 replace the contents of the "__DATA__" section with your own YAML
65 config.
66
67 #!/usr/bin/perl
68 use strict;
69 use warnings;
70 use HTML::FormFu;
71 use YAML::XS qw( Load );
72
73 my $form = HTML::FormFu->new;
74 my $yaml = do { local $/; <DATA> };
75 my $data = Load($yaml);
76
77 $form->populate($data);
78
79 print $form;
80
81 __DATA__
82 ---
83 auto_fieldset: 1
84 elements:
85 - type: Text
86 name: foo
87
88 Unsupported HTML tags
89 You can use the HTML::FormFu::Element::Block element, and set the tag
90 to create any arbitrary pair of tags.
91
92 ---
93 elements:
94 - type: Block
95 tag: span
96 content_xml: "<b>Hi!</b>"
97
98 You can use "content" in HTML::FormFu::Element::Block, "content_xml" in
99 HTML::FormFu::Element::Block or "content_loc" in
100 HTML::FormFu::Element::Block to add any content you wish, or use
101 "element" in HTML::FormFu::Element::Block to add elements.
102
104 You can automatically set defaults using "default_args" in
105 HTML::FormFu, and if you set this in a Catalyst application config
106 file, it'll take effect throughout your entire application, for
107 example:
108
109 myapp.yml
110 ---
111 'Controller::HTML::FormFu':
112 constructor:
113 default_args:
114 elements:
115 Checkbox:
116 reverse_multi: 1
117 Radio:
118 reverse_multi: 1
119
121 Insert a new field before existing form fields
122 See "insert_before" in HTML::FormFu and "insert_after" in HTML::FormFu.
123
124 my $fieldset = $form->get_element({ type => 'Fieldset' });
125
126 $fieldset->insert_before(
127 $form->element(\%specs),
128 $form->get_field($name)
129 );
130
131 Another way to approach the problem is to use multiple config files,
132 and decide which to load at runtime:
133
134 # user_edit.yml
135 ---
136 elements:
137 - type: Text
138 name: email
139
140 # user_username.yml
141 ---
142 elements:
143 - type: Text
144 name: username
145
146 # user_register.yml
147 ---
148 load_config_file:
149 - user_username.yml
150 - user_edit.yml
151
152 # create a user edit form, with only the email field
153
154 $form->load_config_file( 'user_edit.yml' );
155
156 # create a user registration form with username and email fields
157
158 $form->load_config_file( 'user_register.yml' );
159
160 From and Field attributes
161 You can add any arbitrary attributes to a form with "attributes" in
162 HTML::FormFu, or to any element with "attributes" in
163 HTML::FormFu::Element.
164
165 ---
166 attributes_xml:
167 onsubmit: "js_function()"
168 elements:
169 - type: Text
170 name: foo
171 attributes_xml:
172 onchange: "js_function()"
173
175 Check valid dates
176 Use HTML::FormFu::Inflator::DateTime. When the inflator is processed,
177 it will try to create a DateTime object. An error will be returned if
178 the supplied values do not make a valid date.
179
180 Check valid URI / URLs
181 HTML::FormFu::Constraint::Regex supports Regexp::Common regular
182 expressions:
183
184 ---
185 elements:
186 - type: Text
187 name: uri
188 constraints:
189 - type: Regex
190 common: [ URI, HTTP, { '-scheme': 'ftp|https?' ]
191
192 Implement a custom constraint / validator
193 If HTML::FormFu::Constraint::Callback or
194 HTML::FormFu::Validator::Callback isn't sufficient for your needs, you
195 can create your own class that inherits from HTML::FormFu::Constraint
196 or HTML::FormFu::Validator, respectively.
197
198 It should implement a "validate_value" method, which returns true is
199 the value is valid, or false otherwise.
200
201 package My::Custom::Validator;
202 use strict;
203 use base 'HTML::FormFu::Validator';
204
205 sub validate_value {
206 my ( $self, $value, $params ) = @_;
207
208 return 1 if value_is_valid( $value );
209
210 return;
211 }
212
213 1;
214
215 Then add your custom validator to the form:
216
217 ---
218 elements:
219 - type: Text
220 name: foo
221 validators:
222 - '+My::Custom::Validator'
223
224 Constrain one form field based on the value of another
225 For example, you have a radiogroup and several text fields, with
226 different text fields being required depending on the value of the
227 radiogroup.
228
229 This is achieved using the "when" attribute of a constraint:
230
231 constraints:
232 - type: Length
233 min: 8
234 when:
235 field: bar
236 values: [ 1, 3, 5 ]
237
238 In the above example, the Length constraint is only processed when the
239 form field named "bar" has a value of either 1, 3 or 5.
240
241 You can also test for a negative condition using the "not" attribute:
242
243 constraints:
244 - type: Length
245 min: 8
246 when:
247 field: bar
248 values: [ 1, 3, 5 ]
249 not: 1
250
251 Now the constraint will be processed only if the value of field "bar"
252 is NOT 1, 3 or 5.
253
254 Note: if you rely on the value of a checkbox for a when-restricted
255 contraint, you might want to consider setting "default_empty_value" for
256 that checkbox. Take a look at HTML::FormFu::Element::_Field to learn
257 more.
258
259 Please read HTML::FormFu::Constraint for futher information.
260
261 Constrain one form field based on the return value of a callback
262 You can use the "when" attribute of a constraint also to decide using a
263 callback if the constraint should be applied.
264
265 For instance, the following (code) example shows a constraint being
266 applied only if the value of another field contains a pattern
267
268 my $apply_if_pattern = sub {
269 my $params = shift;
270 return 1 if $params->{other_field} =~ m/\A ice_cream \z/xms;
271 return 0;
272 }
273
274 $field->{constraints} = {
275 type => 'Required',
276 when => {
277 callback => $apply_if_pattern,
278 }
279 }
280
281 Please read HTML::FormFu::Constraint for futher information.
282
284 Indented HTML
285 Use HTML::FormFu::OutputProcessor::Indent:
286
287 ---
288 output_processors:
289 - Indent
290
291 Add a blank div (e.g. for AJAX purposes)
292 Simply add a Block element in the relevant place, it defaults to a
293 "DIV" tag.
294
295 ---
296 elements:
297 - type: Text
298 name: user
299
300 - type: Block
301 id: foo
302
303 - type: Text
304 name: email
305
307 Custom error messages
308 If you want to display an error message due to an error in your own
309 code, such as a database check; something which isn't implemented as a
310 Constraint or Validator; you can use a Callback Constraint.
311
312 If you don't provide your own callback routine, the default callback
313 will always pass, regardless of user input.
314
315 You can take advantage of this by setting force_errors, to display its
316 error message when needed.
317
318 Example config:
319
320 ---
321 elements:
322 - type: Text
323 - name: email
324 - constraints:
325 type: Callback
326 message: 'Email address already in use'
327
328 Example usage:
329
330 if ( $@ =~ m/duplicate entry for key 'email'/i ) {
331
332 $form->get_field('email')
333 ->get_constraint({ type => 'Callback' })
334 ->force_errors(1);
335
336 $form->process;
337 # then redisplay the form as normal
338 }
339
340 Highlight required fields (or fields with certain types of constraint)
341 This can be achieved using the form's "auto_constraint_class" method:
342
343 $form->auto_constraint_class( 'constraint_%t' );
344
345 The container divs around any form field with a constraint will then
346 have extra CSS classes added, which indicate the type of constraint and
347 allow you to apply appropriate styling with CSS:
348
349 /* change background of labels for fields with a Required constraint */
350 fieldset .constraint_required label {
351 background: #f00;
352 }
353
354 This technique can also be used to add content before or after the
355 fields in question (note this will not work in older browsers with more
356 limited CSS support such as IE6):
357
358 /* add an asterisk at the end of the label for required fields */
359 fieldset .constraint_required label:after {
360 content: '*'
361 }
362
363 Add a popup hint to a field
364 Some visual browsers (including IE6/7, Firefox, Opera 9) display a
365 tooltip when a user hovers their mouse pointer over an HTML element
366 with a "title" tag. Aural browsers may try to turn the content into
367 speech. You can take advantage of this behaviour to provide a hint to
368 the user about how to complete a form field.
369
370 elements:
371 - type: Text
372 name: country_name
373 label: Country Name
374 attributes:
375 title: Name of country
376
377 The above will provide a hint when the "country_name" field receives
378 focus. Or you could provide the hint for the container tag around both
379 field and label:
380
381 elements:
382 - type: Text
383 name: country_name
384 label: Country Name
385 container_attributes:
386 title: Name of country
387
388 Display filtered values
389 If you have a Filter on a field, such as
390 HTML::FormFu::Filter::Whitespace to strip leading / trailing
391 whitespace, then if you redisplay the form the field is normally
392 populated with the value the user originally entered.
393
394 If you would like the field to contain the filtered value, use
395 "render_processed_value" in HTML::FormFu.
396
398 Installing the TT templates
399 It only makes sense to use the template files if you plan on
400 customising them, as the default "string" render-method is faster.
401
402 If you're using the Catalyst web framework, install
403 Catalyst::Controller::HTML::FormFu and run the following command:
404
405 $ script/myapp_create.pl HTML::FormFu
406
407 This will create a directory, "root/formfu", containing the
408 HTML::FormFu template files.
409
410 If you use Catalyst::Controller::HTML::FormFu as a base class and you
411 don't set HTML::FormFu's INCLUDE_PATH yourself, it will automatically
412 be set to "root/formfu" if that directory exists.
413
414 If you're not using Catalyst, you can create the template files by
415 running the following command:
416
417 $ html_formfu_deploy.pl <target-directory>
418
419 Take note that if you choose to customise your own copy of
420 HTML::FormFu's template files, you'll need to keep track of the
421 "Changes" file, when updating HTML::FormFu, so that you can update your
422 own templates if the core templates are updated.
423
425 Catalyst::Plugin::StackTrace
426 If you're using Catalyst::Plugin::StackTrace, make sure you're using at
427 least version 0.09 - earlier versions had performance problems with
428 "HTML::FormFu".
429
430 Template::Alloy
431 You can also use Template::Alloy instead of Template::Toolkit, it's
432 mostly compatible, and in many cases provides a reasonable speed
433 increase. You can do this either by setting the
434 "HTML_FORMFU_TEMPLATE_ALLOY" environment variable to a true value, or
435 by passing "TEMPLATE_ALLOY" to "tt_args" in HTML::FormFu:
436
437 tt_args:
438 TEMPLATE_ALLOY: 1
439 COMPILE_DIR: /tmp
440 COMPILE_PERL: 1
441
442 Template::Alloy's caching is off by default. Switch it on by setting
443 either "COMPILE_EXT" or "COMPILE_DIR". If you're running under a
444 persistent environment such as modperl or fastcgi, you should also set
445 "COMPILE_PERL" to compile the cached templates down to perl code.
446
447 Of cource, if you wish you can still use Template::Toolkit to process
448 your own application templates, letting Template::Alloy process just
449 the HTML::FormFu templates.
450
451 HTML:FormFu::Preload
452 To reduce the runtime for each form that uses a previously unused
453 element or processor - at the expense of greater memory usage - you can
454 preload all FormFu modules - this is only recommended for persistent
455 environments such as modperl or fastcgi:
456
457 use HTML::FormFu::Preload;
458
460 Force an element to always have a certain value
461 See the following:
462
463 "retain_default" in HTML::FormFu::Element::_Field, "force_default" in
464 HTML::FormFu::Element::_Field
465
467 Will Hawes "wdhawes@gmail.com"
468
469 Carl Franks "cfranks@cpan.org"
470
472 This document is free, you can redistribute it and/or modify it under
473 the same terms as Perl itself.
474
475
476
477perl v5.12.1 2010-05-16 HTML::FormFu::Manual::Cookbook(3)