[html-formfu] DBIC-FormFu extension - Carl?

Carl Franks fireartist at gmail.com
Fri Sep 28 11:32:16 GMT 2007


On 25/09/2007, Mario Minati <mario.minati at googlemail.com> wrote:
> On Wednesday 19 September 2007 12:16:01 Carl Franks wrote:
> > On 19/09/2007, Mario Minati <mario.minati at googlemail.com> wrote:
> > > On Wednesday 19 September 2007 11:02:47 Carl Franks wrote:
> > > > On 18/09/2007, Mario Minati <mario.minati at googlemail.com> wrote:
> > > > > If you have the following form fields:
> > > > >     private_street
> > > > >     private_city
> > > > >     private_email
> > > > >     office_street
> > > > >     office_city
> > > > >     office_email
> > > > >
> > > > > You most likely would like to save both datasets in same table:
> > > > >     my $private = $user->new_related( 'data', { type => 'private' }
> > > > > ); $private->populate_from_formfu( $form, { prefix_col => 'private_'
> > > > > } ); my $office = $user->new_related( 'data', { type => 'office' } );
> > > > > $office->populate_from_formfu( $form, { prefix_col => 'office_' } );
> > > >
> > > > I think a more elegant solution would be by adding support for
> > > > 'nested' params, e.g.
> > > >
> > > > with the following input:
> > > >     "private.street" => x
> > > >     "private.city" => y
> > > >     "private.email" => z
> > > >
> > > > $form->param('private') would return a hashref:
> > > > {
> > > >     street => x,
> > > >     city => y,
> > > >     email => z,
> > > > }
> > >
> > > This idea is more general and useful.
> > >
> > > > (or use the alternative syntax, "private[street]", "private[city]",
> > > > etc.)
> > >
> > > Can we get HTML problems with parameter names including '.' or '[]' (I
> > > favour '.' as it would allow chaining.)
> >
> > There shouldn't be any problems, this approach is already used by
> > CGI::Expand and Catalyst::Plugin::Params::Nested.
> >
> > (The idea was pinched from RoR, which uses it extensively)
> >
> > > > Then do something like:
> > > >
> > > >     $relationship->populate_from_formfu(
> > > >         $form,
> > > >         { param => 'private' } );
> > > >
> > > > Also, it's maybe not immediately helpful in this example, but I'd like
> > > > to break out the logic from Element/Dojo/Repeatable.pm into a core
> > > > Element/Repeatable.pm element.
> > > > This could help with some relationships, as it would provide automatic
> > > > handling of multiple fields by adding an increasing numerical suffix
> > > > to the fieldname.
> > >
> > > Would you do a more deeply change in FormFu, like adding an additional
> > > parameter to fieldset like
> > > - fieldset
> > >     my_parameters_belong_to: private
> > >     elements:
> > >       - type: Text
> > >         name: just_name
> > >
> > > which will lead to 'private.just_name' in HTML code.
> >
> > Yes, this approach.
> >
> > Though I'd probably just name it:
> >     nested: private
>
> After playing and thinking a bit I came over the following points I would like
> to discuss:

btw, both notations support chained names:
    foo.bar.baz
    foo[bar][baz]

Have a form-level nested() which is just a bool test.
Have a separate method to set which notation to use, and have it
default to one of them (I'm not really bothered which).

I imagine HTML::FormFu::Element::nested_name() looking something like this:

sub nested_name {
    my $self = shift;

    croak 'cannot set nested_name' if @_;

    if ( defined $self->name && $self->nested ) {
        my @names = ( $self->name );
        while ( defined $self->parent ) {
            my $self = $self->parent;
            push @names, $self->name
                if defined $self->name;
        }
        if ( $self->form->nested_dotted ) {
            return join ".", reverse @names;
        }
        else {
            my $name = pop @names;
            map { $name .= "[$_}" } reverse @names;
            return $name;
        }
    }
}

> 1.
> We need an additional accessor for the nested name (e.g. processed_name) which
> is given to render and which is used in the templates.
> This has to be done as functions use the name to find elements, so I can't
> just rewrite the name.

Probably.
Though I'm still debating on whether $field->render->name() should
return 'name' or 'nested_name'.
Maybe for now, just go with the simpler change, and change the
templates to use 'nested_name' instead of 'name'.

> 2.
> This might lead into a caveat. Considering a form with to fieldsets for
> addresses names just 'street', 'city', ... and with the a nested Attribute in
> their respective fieldsets. The user cannot access these fields by get_field
> unless we provide a way to use the processed nested name to access the field.
> I propose to autodiscover the way to find the fields by looking at the given
> name and use the processed nested names when there is a '.' or '[]' inside
> the given string.

Extend HTML::FormFu::Util::_get_elements() to support a 'nested_name' argument.

    if ( exists $args->{nested_name} ) {
        @$elements
            = grep { defined $_->nested_name && $_->nested_name eq
$args->{nested_name} } @$elements;
    }

If you want to find a field without using it's full name, they you
should probably be doing:
    $fieldset->get_field($field_name);

> 3.
> At the moment I calculate the nested names in 'process' as I
> extended 'process' in Element and late all children from Element that
> redefine 'process' call it's ancestor.
> Do you know of a better place to do this name preprocessing?

Probably just have a nested_name() method which calculates it on demand.

> 4.
> The param processing is going to be tricky, as like in Catalyst someone might
> have already expanded our parameter names into arrays/hashes, we have to take
> care of that.
> All elements and constraints need to use the processed nested name to access
> their parameter values.
> The param functon needs to be changed as it currently expects a list of names
> for which to get the values, but we no might give an argument 'nested', so it
> has to change to only accept an array ref of names or one name and the ash
> ref with the nested name to prepend.

I think we ought to demand that if you're using $form->nested(1) that
you must also use either Catalyst::Plugin::Params::Nested or
CGI::Expand, so that the input is already in a predictable state.

Carl



More information about the HTML-FormFu mailing list