[html-formfu] insert_before/insert_after and nested forms

Tim Rayner tfrayner at gmail.com
Thu Dec 18 12:05:16 GMT 2008


2008/12/18 Carl Franks <fireartist at gmail.com>:
> 2008/12/17 Tim Rayner <tfrayner at gmail.com>:
>> Hi,
>>
>> I've been trying to use the insert_before() and insert_after() methods
>> to add a new element to a form that is nested (not that nested
>> actually, it just has the auto_fieldset thing going on). I can find my
>> pre-existing elements just fine with get_all_element, but when I try
>> and insert a new element before or after them I get the "position
>> element not found" error. Looking at the code it appears that the
>> insert_* methods only search $self->_elements(), which in my hands
>> only returns the top-level elements, and doesn't do a recursive
>> search. Is this by accident or design? I guess I was expecting these
>> insert_* methods to magically figure out the nesting depth for the new
>> element based on the position element.
>
> I'll think about changing it - I can't off-hand think of any problems
> that it would cause.
>
> I normally use it like so:
>
>    my $field = $form->get_field('foo')
>
>    $field->parent->insert_after( $new_field, $field );

Thanks! I hadn't thought of that (obviously). Works like a charm.

> However, it is a very low-level function, and not particularly recommended.
> It's a bit awkward that you generally need to use a 2nd form to create
> the fields to be inserted.
>
> What I would find more useful, would be a similar function that
> accepts a config structure, rather than an already-created element.
> Something like:
>
>    $form->add_element_after(
>        {   type => 'Checkbox',
>            name => 'foo',
>        },
>        'bar',
>    );
>
> Where the first structure is used to create an element, and the 2nd
> argument is an argument suitable for passing to get_all_element() - or
> optionally it could just be an element object.

Yes, that would be ideal. This is probably way too simplistic (i.e.,
it might work now, but I imagine that maintaining it later could be a
problem); however it does have the advantage of brevity:

sub add_element_after {
    my ( $self, $arg, $position ) = @_;
    unless ( blessed $position ) {   # or however we want to detect an
Element object.
        $position = $self->get_all_element( $position )
            or croak('position element not found');
    }
    my $new = $self->element( $arg );
    return $position->parent->insert_after( $new, $position );
}

In any case, the $field->parent trick seems to work well in my hands;
it might just be worth adding a note on that to the docs.

Thanks,

Tim



More information about the HTML-FormFu mailing list