I definitely agree that designers should be allowed to work in HTML
whenever possible. Not only does it make their lives easier, but they
already have tools to generate all those tedious form tags and make them
look purty.
I'm thinking: why don't we make a solution based on HTML::FillInForm? If
you're using CGI::Application::Plugin::ValidateRM, then you're allready
using HTML::FillInForm to maintain form state between submissions, so
why not use it for the initial state as well?
HTML::FillInForm won't help you generate lists of things for select
menus, radio buttons and lists of checkboxes. For that, you still need a template
loop. But HTM::FillInForm does select the correct item in a list, and
that's a good chunk of the work.
Here's a little script that illustrates how it could work.
It includes two mock CDBI classes, and a little CDBI-to-HTML::FillInForm
bridge.
#!/usr/bin/perl
use HTML::FillInForm;
use strict;
{
# Fake a CDBI 'MyUser' class (hardcoded to 'Roger Rabbit')
package MyUser;
sub create { return bless {} }
sub id {
1;
}
sub first {
return 'Roger';
}
sub last {
return 'Rabbit';
}
sub mailinglist {
return 1;
}
sub profession {
return MyProfession->create;
}
# Fake a CDBI 'MyProfession' class (hardcoded to 'Actor')
package MyProfession;
sub create { return bless {} }
sub id {
return 3;
}
sub name {
return 'Actor';
}
}
{
# Class for translating between Class::DBI and
# HTML::FillInForm
# - Note: doesn't handle has_many fields
package FIF_CDBI_Bridge;
sub new {
my $class = shift;
my %args = @_;
my $objects = $args{'objects'} || {};
my $self = {
objects => $objects,
};
return bless $self;
}
sub param {
my $self = shift;
my $name = shift;
# e.g. user.first
my ($obj_name, $meth_name) = split /\./, $name;
my $object = $self->{'objects'}{$obj_name};
return unless $object;
return unless $object->can($meth_name);
# e.g. $user->first
my $value = $object->$meth_name;
# if we get an object, return $object->id
if (ref $value) {
if ($value->can('id')) {
$value = $value->id;
}
}
return $value;
}
}
my $form = <<EOF;
<form>
<br />First Name: <input type="text" name="user.first">
<br />Last Name: <input type="text" name="user.last">
<br />If you have a <i>really</i> long last name, use the
textarea:
<br /><textarea name="user.last"></textarea>
<br />On mailing list: <input value="1" type="checkbox" name=
+"user.mailinglist">
<br />Profession (radio):
<br /><input type="radio" name="user.profession" value="1">Do
+ctor
<br /><input type="radio" name="user.profession" value="2">La
+wyer
<br /><input type="radio" name="user.profession" value="3">Ac
+tor
Profession (select):
<select name="user.profession">
<option value="1">Doctor
<option value="2">Lawyer
<option value="3">Actor
</select>
</form>
EOF
my $user = MyUser->create;
my $bridge = FIF_CDBI_Bridge->new(
objects => {
user => $user,
}
);
my $fif = new HTML::FillInForm;
my $output = $fif->fill(scalarref => \$form, fobject => $bridge);
print $output;
The form is all HTML, and creates multiple views of the same data. For
instance, the last name is displayed with both a regular text input tag
and also a textarea tag. The profession is represented by both a list
of radio buttons and a select menu.
In an application, the bridge would be run after the template has been
filled out but before the text is returned to the browser.
I'll play around with this some more and try to turn it into a proper
module.
Michael
edit: fixed a brain-o where I mixed up textareas and checkboxes
edit: fixed a typo
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.