Friday, April 20, 2012

Rendering with blocks in HTML::FormHandler

When rendering, FormHandler loops through the sorted fields in the form and executes the 'render' method on each field. Fields in FormHandler forms, particularly those that interface with a database, are usually structured in a way that matches the data structure. This doesn't always fit with the way that you want to display the form.


'Blocks' provide an alternative way of structuring the display. A 'block' is a fairly basic object that contains a 'render' method. The standard block class, HTML::FormHandler::Widget::Block, has Moose attributes to set the HTML tag, the label, the classes, etc, plus a 'render_list' which contains the names of a list of fields or other blocks to render.


You create a block with 'has_block':

has_block 'comment' => ( tag => 'p', content => 'This is a comment',
        class => ['comment'] );

Blocks can contain lists of fields:


has_block 'fset1' => ( tag => 'fieldset', render_list => ['foo', 'bar'] );

In order to use blocks when rendering instead of fields, you need to provide the form with a 'render_list' too (in addition to any render_lists that might exist in the blocks).


sub build_render_list { ['fset1', 'comment', 'a_field' 'submit_btn' ] }

A complete form that renders using blocks:


package MyApp::Test::Form;
    use HTML::FormHandler::Moose;
    extends 'HTML::FormHandler';

    sub build_render_list {['abc', 'def', 'ghi', 'submit_btn']}
    has_field 'foo';
    has_field 'bar';
    has_field 'flim';
    has_field 'flam';
    has_field 'fee';
    has_field 'fie';
    has_field 'fo';
    has_field 'fum';
    has_field 'submit_btn';
  

    has_block 'abc' => ( tag => 'fieldset', render_list => ['foo', 'fo'] );
    has_block 'def' => ( render_list => ['bar', 'fum'], label => "My DEF Block",
        label_class => ['block', 'label'] );
    has_block 'ghi' => ( render_list => ['flim', 'flam'], wrapper => 0 );



More flexible form rendering in Perl with FormHandler....



Monday, March 8, 2010

HTML::FormHandler result object

Sometime last year I re-structured HTML::FormHandler so that the input and values that are produced by the form validation process are stored in separate result objects. There is an alternate method 'run' (as opposed to the usual 'process' method) to get these objects, or you can get them from a form after 'process'.

I expected that those who were interested in using this would materialize and provide input into what additional facilities/hooks were needed, but as far as I can tell nobody has actually used the feature. I think that it's a fair assumption that nobody actually knows about it, or can't figure out the point.

The standard way to use FormHandler is (simplified) something like:

    my $form = MyApp::Form->new;
    $form->process( params => $params, item => $item, ...);
    if( $form->validated ) {
     ....
    }

When using the the result object, the form acts like a kind of factory, and it looks like this:

    my $form = MyApp::Form->new;
    my $result = $form->run( params => $parsms, item => $item, ... );
    if( $result->validated ) {
       ...
    }

...and all the state is stored in the result objects, ideally leaving none left in the form

Currently result objects refer back to some attributes of the form object for rendering, since a number of rendering related definitions are stored there. It would be possible to decouple that, but then you'd end up having to define the validation and rendering aspects of the fields in two places.

In practice, the separation between static (form definition) information and ephemeral data is not nearly as clearcut as you might think. I find that people often want to change attributes that would probably be initially defined as static based on values that are passed in. It is possible to do this in a clean way, of course. But since the previous results are always cleared out at the beginning of each 'process' call, in practice the difference between using the form with 'process' and using it with 'run' aren't huge.

Nonetheless, I am sure there are people who have good use cases for this alternative architecture, and would love to have people pound on it and use it.

Sunday, February 21, 2010

creating a FormHandler form from a DBIx::Class result source

Someone regularly pops up in #formhandler looking for a way to automatically create a form from a DBIx::Class result source. After explaining how to create a fairly simple role that would do that, the people have always gone away and nothing ever came of it.

I have mixed feelings about the idea, myself. Sure, there's a theoretical benefit to not defining things in multiple places. But in practice, there's almost always differences in selection, presentation, etc, that mean that an automatically derived form is of surprisingly little use. At least in my experience. YMMV. It's awfully easy to take the list of column names and type "has_field 'column';"

But then the eleventeenth person asked about automatic form generation - and the yaks must have been particularly hairy this weekend...because I made a good start at shaving this particular one.

There is now a new trait: HTML::FormHandler::TraitFor::DBICFields, and a package to do the mapping from source info to field definitions: HTML::FormHandler::Model::DBIC::TypeMap. I'm pretty sure that it's not quite right yet, but at least a start has been made, and it should be easier for those that want this kind of functionality to polish, add, and tweak. For one thing, it doesn't handle relationships yet. FormHandler can create form fields out of a lot of the standard DBIx::Class relationships, yet it is often not what you would want to have happen automatically. So I think skipping relationships as a default is probably OK.

Anyway, here is how to create a form by looking at the source columns:

   my $book = $schema->resultset('Book')->find(1);
   my $form = HTML::FormHandler::Model::DBIC->new_with_traits( 
      traits => ['HTML::FormHandler::TraitFor::DBICFields'],
      field_list => [ 'submit' => 
          { type => 'Submit', value => 'Save', order => 99 } ],
      item => $book );

The field_list attribute is because I thought it was better to explicitly specify the submit field, rather than automatically create it. I could be argued out of it...

The interface is only a few hours old, so if you have thoughts about how this should work, this is the time to speak up, before somebody starts using it and it becomes harder to change. :-)

Speaking of dynamic forms... HTML::FormHandler is known for it's Moose-y sugar interface, but there are other ways to create a FormHandler form. Using a 'field_list' as a parameter to 'new' works fine to create a dynamic form (though there are things that are possible inside a class that just can't be done with that kind of interface):

my @select_options = ( {value => 1, label => 'One'}, 
       {value => 2, label => 'Two'}, {value => 3, label => 'Three'} );
my $args =  {
    name       => 'test',
    field_list => [
        'username' => {
            type  => 'Text',
            apply => [ { check => qr/^[0-9a-z]*/, message => 
                   'Contains invalid characters' } ],
        },
        'password' => {
            type => 'Password',
        },
        'a_number' => {
            type      => 'IntRange',
            range_min => 12,
            range_max => 291,
        },
        'a_select' => {
            type    => 'Select',
            options => \@select_options,
        },
        'sub' => {
            type => 'Compound',
        },
        'sub.user' => {
            type  => 'Text',
            apply => [ { check => qr/^[0-9a-z]*/, 
               message => 'Not a valid user' } ],
        },
        'sub.name' => {
            type  => 'Text',
            apply => [ { check => qr/^[0-9a-z]*/, 
                message => 'Not a valid name' } ],
        },
        'submit' => {
            type => 'Submit',
        },
    ]
};
my $form = HTML::FormHandler->new( %$args );

And of course you can use one of the rendering roles, HTML::FormHandler::Render::Simple, or the rendering widgets, or write your own renderer... Too Many Ways To Do Things (tm).

Wednesday, August 26, 2009

Moose: adding attributes to a base class

I'm using FormHandler for an example here, but the technique is general.

FormHandler forms are Perl classes with a number of attributes including an array of Field classes with another (probably too large) number of attributes. A few of the field attributes are validation and data related, but a lot of the other ones are related to producing HTML for display. Despite the too many attributes in the field classes, users still want yet more attributes. One of the FormHandler users was developing forms that used a javascript form package and wanted to interface the FormHandler forms to the javascript forms. To do this, he wanted an additional attribute in the fields to store information that would be used by extJs.

One possibility would be to subclass every last single field and add an additional attribute. This does not sound like either fun or a good idea. A much better alternative was to use Moose to add attributes to the base class by applying a role containing the attributes.

So I started out by creating a small role containing a single attribute:

   package MyApp::Field::Extra;
   use Moose::Role;
   has 'my_extra_attribute' => (is => 'rw', isa => 'Str' );
   1;

Now I needed someplace to apply the role. The BUILD method of the user form looks like a good place. Like good Moose classes, all of the fields have '__PACKAGE__->meta->make_immutable' in them. So in order to apply a role we have to temporarily make the class mutable and then make it mutable again. So I make the class mutable, apply the role using Moose::Util, then make it immutable again:

   my $class = 'HTML::FormHandler::Field';
   $class->meta->make_mutable;
   Moose::Util::apply_all_roles( $class->meta, ('MyApp::Field::Extra'));
   $class->meta->make_immutable;

Using a test file I make a form class using this code in the BUILD method, create an instance of the form, and find that the fields now have an additional attribute that I can retrieve and set.

This looks good until I try to set the new attribute in a 'has_field' declaration:

   has_field 'my_field' => ( my_extra_attribute => 'some_value' );

Ooops. This doesn't work. I'd forgotten that the fields are constructed in the base class BUILD method which fires before my form class's BUILD method. So now I need someplace else to move my role setting that will happen before the base class BUILD. Maybe after BUILDARGS...

   after 'BUILDARGS' => sub {
      my $class = 'HTML::FormHandler::Field';
      $class->meta->make_mutable;
      Moose::Util::apply_all_roles( $class->meta, ('MyApp::Field::Extra'));
      $class->meta->make_immutable;
   };

This works. Now I can treat the new attribute just like an original field attribute. And it's a lot easier than subclassing every field...

There are other ways of achieving the same thing. You could add an attribute instead of applying a role. But roles are more general purpose and flexible, so I'm satisfied with this solution for now.

And I definitely <3 the flexibility that comes with Moose.

Sunday, August 2, 2009

Fields: Moose attributes or arrays of objects?

Moose attributes are lovely things. They're a part of Moose that helps to make programming fun again. But having a magical, Dr. Who screwdriver doesn't mean that you can lose all of your other tools. If you have a nail, a good old-fashioned hammer is the right tool.

Moose type constraints are great things to catch programmer errors, typos, incorrect objects. Throwing errors for this kind of type failure is a good thing. You want the programmer to notice that something has gone wrong even if he hasn't had his morning coffee. I first did object oriented programming with C++. I still remember all the hoops that we had to jump through to handle construction time errors (many C++ compilers didn't have exceptions yet). The problem of what to do if you can't create a valid object is the problem that Moose attributes are designed to solve, and throwing errors is the proper thing to do.

But in my opinion, when the task is validation, not construction of a valid object, throwing errors isn't always the best way. You want to take an input string, hand it to the validator which examines it and hands it calmly back saying "good" or "not good", or some more specific error message which can be presented to a user--a user who is not the programmer. Handing it to a construct which instead has a tantrum and throws it back at your head - picture the programmer frantically dodging this way and that, trying to catch the message and de-cipher the problem to present some reasonable message to the user - introduces unnecessary difficulties.

When I started doing the work that turned into HTML::FormHandler I looked at the possibility of turning the field objects into Moose attributes, and saw a number of problems. One of the problems was simply names. Any attribute in the form that was not a field became a name that was not allowed as a field name. This sucked. Of course the programmer could pick some other name and have some additional attribute trait that specified the "real" field name. Yuck, but I suppose it would have worked.

There was a lot of functionality in the field class already, so it seemed to make most sense to have the attributes be of a field object type. But then the Moose attribute type validation doesn't actually apply to the job of the field classes -- validation -- but instead to whether or not this is a valid field, which is appropriate but not the same thing at all. Moving all of the attributes in the field class into some Moose attribute metaclass didn't appeal at all. I didn't see the point. The fields worked fine as objects. If you didn't ever want to provide assistance in constructing HTML or allow validation using simple object methods or an endless list of other things, I suppose you could go in that direction. But I already had working code and working functionality that I liked that I wasn't willing to give up for no reason other than ... um, fashion? Mooseish purity?

So there would be a bunch of Moose attributes that had a field class type. Then you need to be able specify all of the attributes to use to construct the fields. This is not insurmountable, but to do it in a non-irritating way (for me) would require some Moose-ish sugar. Fine, that would work. The next problem is that the fields are really a kind of set and you often need to iterate over them. So there would need to be some kind of array (or other collection) pointing to all of these objects. This was starting to look suspiciously like the array of field objects that I already had.

At this point I started wondering what advantage there was to making the fields Moose attributes. Sure, you could do $form-> sometimes. If the field name didn't conflict with other attributes. But I was already planning to have nested sub-fields and arrays of repeatable fields and that model didn't fit well at all with the Moose attribute idea. It's not like it was necessary to be able to do method modifiers or other Moose-ish things on the fields. They were objects. You could do whatever you wanted in them already. You could already use method modifiers (etc) on all of the parts of the form validation process.

I'm sure there would have been some way of making fields-as-Moose-attributes work. But this is Just A Program. The idea is to make it work in as simple a way as possible (but no simpler), not to make sure that it uses the latest shiny thing whether it provides any advantage or not. (Well, that's my goal anyway. Your goal may be playing with shiny new technologies and tools. :) )

The Collection::Array of field objects was working fine. It's still working fine. I still don't see any advantage to turning the fields into Moose attributes that isn't canceled out by some other disadvantage or complication. The current architecture, which I'm happy with, would be just silly shoehorned into a bunch of Moose attributes.

I guess I won't win the Most Unnecessary Moose Metaprogramming (MUMM) award (which it sometimes seems to me that the Mooserati are competing for). Shrug.

Saturday, July 18, 2009

why HTML::FormHandler...

Dan Dascalescu (dandv) said about FormHandler that it "would be awesome if the POD could mention what's different from FormFu, why create the module at all." I have tried to put some of that into the pod, but apparently it's not enough. So I've been thinking about this issue (the problem of too many packages and not enough info on the differences), and I think that there's are a number of things getting in the way of being clear enough and loud enough with "what's different".

For one thing, Carl Franks and many other people have put lots of work and time into FormFu and like it. The reasons that HTML::FormHandler exists are personal, very human feelings and reactions that don't belong in "official documentation". In order for the statements about what I think to not be offensive, they have to be put into the form of: "This is the way I feel, this is the way I reacted. YMMV." I don't want to start a flame war and I don't want to hurt anybody's feeling. (Yeah, I know that's kinda girly. So sue me.)

The next problem is that I don't really know FormFu. When I was looking for a form package a year and a half ago I looked at it and I just could not bring myself to use it. I hated it on sight. So I'm not competent to compare FormHandler and FormFu. (Anybody willing to submit a doc patch who has used FormFu?)

The last problem is that I don't think that I'm necessarily the right person to be really loud and clear about the advantages of FormHandler. I'm too close to it. It would feel like I'm tooting my own horn, boasting. I'm almost certainly not going to be seeing its weaknesses clearly. I think that somebody else will have to make the definitive comparison.

I guess I can talk about why FormHandler exists, but many of the reasons are human reasons, not technical reasons.

Programmers have emotions, sometimes strong emotions, about the tools and libraries that they use. Some packages are clean, easy, fun. Modifications can be made easily. The pieces can be clumped together in ways that are accessible and readable. Programmers can have strong emotions about variable names. So clearly they're a little unbalanced. (You should have seen the arguments that me and my manager had about whether a database column should be named 'report_no' or 'report_num'. It was downright silly but we both had emotions that were too strong to give up our positions. About a database column name.) Sometimes the emotions are irrational, or intuitions based on experience that can't easily be put into words.

So I'm trying to remember why I looked at FormFu and thought: "Yuck. I'm not going to use that. No, no, no." (Warning: this may not be helpful to you in making a choice of packages.)

The first problem that I had with FormFu was the yaml config files. I hate YAML. With a passion. I think that whitespace sensitive formats are stupid. I hated hated hated the tab-sensitivity of make files, and YAML was just more of the same. My eyes/brain can't adjust to pulling out the significant information when I glance over a YAML file. Yes, I KNOW that FormFu can use any kind of Config::General format. But all of the documentation was in YAML and I Didn't Want to Look at It.

There. I told you this wasn't going to be a rational technical discussion, didn't I?

I also hated the fact that the forms were even defined in config files to start with. I looked at it, and my first thought was: but what if I want to do something in a way that hasn't been pre-defined? Yes, I know you can make your own constraint classes, yadda, yadda, yadda. It was too disconnected to the particular form. I looked at the way it worked and I got claustrophobia. I felt like I would be having to adapt myself to FormFu, instead of me being able to adapt FormFu to the way I wanted to work. FormFu code couldn't be easily subclassed or overridden for a particular form. You'd have to do something weird to change the way that it worked. I have no idea if my reaction was accurate or not. I couldn't bring myself to try it enough to find out.

It felt heavyweight, cumbersome, and rigid. And no, I can't give you detailed list of why it felt that way to me. I read the documentation and listened to people complain in #catalyst, and that was it.

Speaking of #catalyst, that was a big source of my dislike for FormFu. Lots of people showed up trying to do something particular with HTML and could not figure out how to do it. I saw people spend days on HTML changes that would have taken them minutes by hand. I saw how hard it was to figure out how to achieve particular results (that I can't remember anymore). This may be totally unfair of me. Maybe boatloads of people will eventually show up complaining about FormHandler in the same way. But I'm trying to be honest here (painfully so, maybe). And those complaints did play a part in my disinclination to use a package that was so hard to customize.

So I looked at the other options out there. Formbuilder was deprecated. Rose Forms was ok, but not quite right. Reaction was interesting but overkill for my application. I found Form::Processor, and it certainly wasn't perfect, but at least the thought of using it didn't depress me. I liked the architecture and I liked the way that it could automatically save forms to the database. The problem was that it didn't have a DBIC model. I decided to write one.

Unfortunately Form::Processor had almost no tests. It had a few field tests, and a small handful of non-database form tests. There were NO tests for interfacing with the database. There were no examples for interfacing with the database. So the first thing I had to do was create a CDBI example so that I could figure out how a DBIC model would work. Eventually I got the DBIC model to work, and uploaded my first package to CPAN. They did not come and arrest me for inadequate code.

I was happy enough with Form::Processor for quite a while. Then I started to use Moose in most of my new code. Form::Processor used Rose::Object. I really liked Moose and it seemed silly to be using two different object systems. The Form::Processor code, because it used Rose::Object, looked easy to convert to Moose. So in a burst of energetic yak shaving, I converted it to Moose.

Bill Moseley, the owner of Form::Processor, had some interest in moving toward Moose, but he didn't have time to work on it. There was no public repository. He had a suite of tests he wanted it to pass that I didn't have access to. There were many Moose features that couldn't be used and feature improvements that couldn't be done because they wouldn't be compatible with Bill's codebase.

I was getting some interest in a Moosified form processor from other programmers and I liked how my new code was shaping up. So I put the code up on github and released it to CPAN. Followed by deafening silence. But I had been communicating with Zbigniew Lukasiak about the new project and he had lots of experience with FormFu and ideas he wanted to try out, so he joined the project, which was a godsend. It's so much better to have other progammers contributing too.

So now it's six months from the first CPAN release. I've gotten a lot of positive feedback from people who've used it who like it. The codebase feels more stable now and we've implemented most of the large features we had in mind (though we're hoping for better rendering in the future...)

We've tried hard to make the API consistent, we've refactored to support compound and repeatable fields. We have a comprehensive test suite. It still seems to be very easy to customize - Moose helps with that. To me, it feels flexible, not cumbersome and rigid. You can use hand-built HTML if you want. The rendering is straightforward and simple to a fault. Adding new features has not been painful. I'm happy with it. YMMV.

I suspect that this was NOT what Dan had in mind with his request for 'why create the module at all'. It might be of more interest to a sociologist studying open source than somebody looking for reasons to pick a package. But it is the answer that I have, such as it is.

Perl Blogging for personal satisfaction

Okay, so I suck at dealing with certain sorts of motivational programs. In another persona I write fiction. Fiction writers have this quaint concept BIAW - Book In a Week. It's not really a book in a week. It's a group of writers who get together and commit to some writing goal in the beginning, and then cheer each other on, or boo and hiss. Whatever. It's SUPPOSED to be motivational. The idea is that committing yourself to a public goal like that is supposed to motivate you to actually do it, since you will (theoretically) be ashamed of not meeting your goal. Or be inspired by the achievements of others. Or something.

I tried joining these sorts of BIAW programs on multiple occasions. And then I noticed something odd. I was writing MORE when I wasn't enrolled in some BIAW program than when I was. Sigh.

Apparently I'm not inspired enough by the idea of not achieving what I said I would in front of other people. It actually has a *cough* negative affect. I blow off a day, and then I start resenting the whole thing. It becomes a chore, a drag, some irritating task that I'm "supposed to" be doing. It's not fun anymore.

And the Perl ironman thing has started to have the same feeling for me. Not the fault of the idea. The idea is great. It's just me and the idea that don't get along.

So in an attempt to actually fulfill the spirit of the Ironman challenge (as opposed to the rules - ewww, rules, I hate rules) henceforth I'm not going to even TRY to meet the rules for achieving the various IronPerson levels. Instead - *gasp* - I'm going to blog about Perl and programming when I feel like I have something to say. The habit has started - and that was the whole point, after all.

Now the only remaining question is ... can I think of some clever riff on Ironman for my personal perl blogging program? Um ... the MarshmallowMan? I know! the StayPuftMan!

Now that I have an inspiring symbol and everything, I can stop. I'm happy now.