<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Wolfgang Kinkeldei</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/wolfgang_kinkeldei1/" />
    <link rel="self" type="application/atom+xml" href="http://blogs.perl.org/users/wolfgang_kinkeldei1/atom.xml" />
    <id>tag:blogs.perl.org,2009-11-03:/users/wolfgang_kinkeldei1//899</id>
    <updated>2011-07-06T21:08:02Z</updated>
    <subtitle>A blog about the Perl programming language</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type Pro 4.38</generator>

<entry>
    <title>Dynamic Forms with HTML::FormFu</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/wolfgang_kinkeldei1/2011/07/dynamic-forms-with-htmlformfu.html" />
    <id>tag:blogs.perl.org,2011:/users/wolfgang_kinkeldei1//899.1947</id>

    <published>2011-07-06T20:33:37Z</published>
    <updated>2011-07-06T21:08:02Z</updated>

    <summary>Recently, we had to rework a legacy project using Catalyst. We chose HTML::FormFu as our Form engine because we had good experience with it in other projects. However, we had to face one problem: Forms had to be different for...</summary>
    <author>
        <name>Wolfgang Kinkeldei</name>
        
    </author>
    
        <category term="Catalyst" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="HTML::FormFu" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="catalystform" label="Catalyst Form" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/wolfgang_kinkeldei1/">
        <![CDATA[<p>Recently, we had to rework a legacy project using Catalyst. We chose HTML::FormFu as our Form engine because we had good experience with it in other projects.</p>

<p>However, we had to face one problem: Forms had to be different for every user. Well, the difference is based on the user's roles, to be precise.</p>

<p>As a rescue and a generic approach, we chose to create a simple HTML::FormFu::Plugin that can get applied to every or some of the forms, just as needed. To get things working, we need to do two things:</p>

<ul>
	<li>mark certain fields inside the form with the rights we need for editing</li>
        <li>have our plugin make the privileged fields readonly</li>
</ul>

<p>A simple form (in perl syntax) might look like this:</p>

<pre>
{
    auto_fieldset => 0,
    elements => [
        {
            type => 'Text',
            label => 'Artno',
            name => 'artno',
            # require admin rights to edit artno
            stash => { rights => 'admin' },
            # also possible for marking fields (but visible in the HTML Markup): 
            attributes => { 'data-right' => 'admin' },
        },
        {
            type => 'Text',
            label => 'Name',
            name => 'name',
        },
    ],
    plugin => 'FixFields',
}
</pre>

<p>And the plugin is a package HTML::FormFu::Plugin::FixFields looking like that:</p>

<pre>
package HTML::FormFu::Plugin::FixFields;
use Moose;
extends 'HTML::FormFu::Plugin';

<p>sub process {<br />
    my $self = shift;<br />
    <br />
    my $form = $self->form;<br />
    <br />
    foreach my $field (@{$form->get_all_elements}) {<br />
        next if !$field->{stash};<br />
        next if !$field->{stash}->{rights};<br />
        <br />
        if ($field->{stash}->{rights} eq 'admin') {<br />
            # only editable for admin, just hide to demonstrate<br />
            $field->attributes->{readonly} = 1;<br />
        }<br />
    }<br />
}</p>

<p>1;<br />
</pre></p>

<p>As a prove of concept, we just hide every field that is marked with <code>stash => { rights => 'somename' }</code>. Every other logic at this place is possible as well.</p>

<p>Conclusion: keeping your controllers slim by making forms intelligent is possible and simple.</p>

<p>PS: yes, repeating things is ugly. Marking every form with <code>plugin => 'FixFields'</code> is bad. Moving this entry to a global config file is also possible. Just add a constructor entry to your config file like this (again in perl format):</p>

<pre>
    'Controller::HTML::FormFu' => {
        constructor => {
            plugins => [ 'FixFields' ],
        },
    },
</pre>
]]>
        
    </content>
</entry>

</feed>
