|
|
| |
Form::Sensible::FAQ(3) |
User Contributed Perl Documentation |
Form::Sensible::FAQ(3) |
Form::Sensible::FAQ - Answers to questions about how to use Form::Sensible
- I have a hash that contains the field values, what's the best way to get
those into a Form::Sensible form?
- There are two ways to do this. The preferred way is usually to delegate
your form's field values to your hash. You often want to do this to link a
form's fields to a single source of data, for example, Catalyst's
"$c->req->params" hashref. This
can be done easily using the Form::Sensible::Form's
delegate_all_field_values_to_hashref routine:
$form->delegate_all_field_values_to_hashref($c->req->params);
After that, all fields will get and set their values via the
"$c->req->params" hashref.
NOTE that this is actually a very bad idea if your forms
are persistent from one request to the next, as the
"$c->req->params" from the initial
request will be captured within a closure. If you are using persistent
forms, you must re-set the delegate during each request or use an
intermediate object instead that can obtain the current request's
parameters.
If you have not delegated your field's values to something
else (as indicated above), the form itself will store the values. In
this case, you must push the values into the form object instead. You
can accomplish this by calling
"$form->set_values($your_hashref);"
- How do I disable a field?
- Simply set the field's '"editable"'
attribute to false. "Form::Sensible"
will ensure that the field is not editable by the end user. Note that when
a field is disabled in HTML, the browser does NOT send the value when the
form is submitted. "Form::Sensible"'s
HTML renderer takes this into account and if a value exists on a field
that is marked as not editable, a hidden field will be added to transport
the value back to the form processor.
- Can I set the options for my Select field directly from a DBIx::Class
resultset?
- Yes. This is actually quite easy. You define an
"options_delegate" on the Select field
and use a subroutine similar to the following:
## defined as a named subroutine so that it can be reused as often as needed.
sub get_options_from_rs {
my $caller = shift;
my $option_details = shift;
$option_details->{rs}->reset;
return [
map {
name => $_->get_column($option_details->{name_column}),
value => $_->get_column($option_details->{value_column})
} $option_details->{rs}->all()
];
}
Then set the
"options_delegate" to use that
function and pass the appropriate information:
$field->options_delegate( FSConnector( \&get_options_from_rs,
{
rs => $your_resultset->search({ ... }),
name_column => 'name',
value_column => 'id',
}
));
The FSConnector will pass your
"option_details" hash to the
"get_options_from_rs" function, and
your options will be pulled from the database when they are needed
(whether for validation or for display).
- How do I create validation that involves multiple fields (like password
and confirmation fields)?
- Individual field based validation is handled via the individual field's
"validation" hash. If you want to check
multiple fields together you need to do whole-form level validation. This
can be accomplished easily via the form's
"validation" hash as follows:
$form->validation({
code => sub {
my ($form, $result) = @_;
if ($form->field('password')->value() ne $form->field('password2')->value()) {
$result->add_error('password2', 'Passwords do not match');
}
}
});
- How do I style forms created by "Form::Sensible"'s HTML
renderer?
- Each element created by
"Form::Sensible"'s HTML renderer is
thoroughly marked up for CSS styling. Each element has a CSS ID and one or
more classes. While the best way to decipher these is to simply generate a
form and look at the IDs and classes on each element, we will endeavor to
give you somewhat of a road map here.
First, all CSS ids and classes are prefixed. This prefix is
'"fs_"' by default. It can be
overridden by passing a css_prefix attribute in the
"default_options" passed to the HTML
renderer's "new()" method. For the
remainder of this explanation, we will assume that the default prefix of
'"fs_"' is in use. The name of the
form is also used in most IDs and classes. For the remainder of this
explanation, we will use 'login' as our form name.
First, each form is contained within a div. The div has an id
of '"fs_"' + the name of the form +
'"form_div"'. So, for our 'login'
form, the ID of the div would be
'"fs_login_form_div"'. The containing
div will also have two classes applied to it:
'"fs_form_container"' and
'"fs_login_form_container"'
The form element itself has an ID of
'"fs_"' + form name +
'"_form"' and again has two classes
applied to it: '"fs_form"' and
'"fs_login_form"'
A complete example of the form start from above would be:
<div id="fs_login_form_div" class="fs_form_container fs_login_form_container">
<form action="/formtest/submit" method="post" id="fs_login_form" class="fs_form fs_login_form" accept-charset="utf-8" enctype="multipart/form-data">
Each field in the form has a CSS id and several classes. For
fields, the form name, the field's name, and type are taken into
account. Because there are so many classes and elements involved, we
will simply provide an example based on the rendering of a text field
called 'username' in the 'login' form.
<div id="fs_username_div" class="fs_formfieldline fs_text fs_username">
<label class="fs_label fs_text_label " for="fs_test_username_input">Username</label>
<input type="text" id="fs_login_username_input" class="fs_input fs_text_input fs_username_input " name="username" />
</div>
Note that for the default template scheme the div that
includes the field and its label always has a class of
'"fs_formfieldline"' in addition to
classes based on the field's type and field name.
Certain field types have more complex rendering and therefore
have more complex CSS id and class mappings (e.g., Select fields). The
best way to understand these is to simply look at the results of
rendering them.
One last thing to note is that when a field is disabled by
setting the 'editable' flag on the field to false, an additional class
of '"noteditable"' will be added to
the input element.
- How do I tell "Form::Sensible" about my own custom
templates?
- "Form::Sensible" is built to allow you
to easily switch themes or override individual fields or field types. In
order to override the builtin templates, you must tell the renderer where
your templates are. You do this by passing an 'additional_include_paths'
parameter to the HTML renderer constructor:
my $html_renderer = Form::Sensible::Renderer::HTML->new({ additional_include_paths => [ '/path/to/your/templates' ] });
#### OR #####
my $html_renderer = Form::Sensible->get_renderer('HTML', { additional_include_paths => [ '/path/to/your/templates' ] });
Once you have done this,
"Form::Sensible" will look in the
directory or directories provided first for its templates, falling back
to the pre-installed templates when a particular template is not
found.
- How do I override a field's template or change the field wrapper?
- When rendering in HTML, for a given field the form name, field name and
field type are all taken into account when searching for overrides. Let's
assume you have a Form called 'login_form' and a 'username' text field.
"Form::Sensible"'s HTML renderer looks
for templates (in its include_paths) in the following order and the first
one found will be used:
login_form/username_field.tt
login_form/text.tt
username_field.tt
text.tt
This allows you to customize any field on any form by name or
by type. Further, you only need to define the template for the items you
wish to override. Anything not found here will fall through to the
default templates that ships with
"Form::Sensible".
- I don't like the way labels for my fields are rendered, Can I change
that?
- Yes. Use the methods described above to tell the HTML renderer where to
look for your additional templates. Then simply create a
'field_wrapper.tt' template file. This is a standard Template::Toolkit
wrapper file. You will have access to all the field information about the
field as "field" and the rendered input
element will be placed wherever you put the string
"[% content %]".
- I would like to change or add information to the start or end of my form,
how do I do that?
- Use the methods described above and provide one of the following templates
(assuming your form is called 'login_form'):
## for form start
login_form/form_start.tt
form_start.tt
## for form messages (errors and status)
login_form/form_messages.tt
form_messages.tt
## for form_end:
login_form/form_end.tt
form_end.tt
Note again that this allows you to change form start,
messaging or ending on a per-form basis or globally for all forms.
See Form::Sensible::Delegation.
- How do I localize field names and error messages?
- Localization of forms can be accomplished through the use of delegates.
Both the Form::Sensible::Validator class and
Form::Sensible::Renderer::HTML::RenderedForm support localizing through
delegates.
By providing a
"DelegateConnection|Form::Sensible::DelegateConnection"
to Form::Sensible::Validator's message_delegate you can translate the
error or status messages as necessary.
You can translate field names in the form in the same way by
providing a
"DelegateConnection|Form::Sensible::DelegateConnection"
to Form::Sensible::Renderer::HTML::RenderedForm's
display_name_delegate
- I'm using Catalyst and I would like my form objects to be persistent from
one request to the next, how do I do that?
- BEWARE: Here lie Monsters and really freaky problems
Generally speaking, it is a bad idea to persist forms from one
request to the next within Catalyst. The main reason is that you can not
reliably delegate in many cases because many of Catalyst's objects (such
as Models and Controllers) can be created and destroyed within the
request lifecycle in certain scenarios. This can be very difficult to
predict and is prone to accidental breakage and bleed over.
If you feel you must try to do this, you have two options:
- 1.
- Ensure that none of your delegation is tied to Controllers or Models (or
any other Component) that might use the context $c
to do its job.
- 2.
- Create and persist 'skeleton forms' that contain no delegation
information, clone them per request and initialize the delegate
connections on the newly created clone form.
If you do not take care to use one of these approaches, you are
going to experience problems ranging from weird data consistency problems to
full scale bleed over of form data between users. Considering the problems
inherent to doing this, how to accomplish it is left as an exercise to the
reader.
NOTE: Persisting the basic form definition hash (as passed
to "Form::Sensible"'s create_form routine)
is not similarly problematic, though care should be taken to ensure that you
don't accidentally capture $c when creating your
delegates. If, after reading the above you still want to know how to do this
properly, drop by the "#form-sensible" irc
channel on "irc.perl.org" and we may be
able to help.
- Where can I go for help using "Form::Sensible"
- You can join the google discussion group:
<http://groups.google.com/group/formsensible>
OR look at the wiki:
<http://wiki.catalyzed.org/cpan-modules/form-sensible>
OR drop by the irc channel:
irc.perl.org#form-sensible Join #form-sensible via your web
browser <http://mibbit.com/#form-sensible@irc.perl.org>
Jay Kuri, "jayk@cpan.org"
Ionzero LLC. <http://ionzero.com/>
Copyright (c) 2010 the aforementioned authors. All rights reserved. This program
is free software; you can redistribute it and/or modify it under the same
terms as Perl itself.
Visit the GSP FreeBSD Man Page Interface. Output converted with ManDoc. |