[html-formfu] Displaying 2 forms in the same page
Andreas Marienborg
omega at palle.net
Thu Oct 16 09:04:58 BST 2008
On Oct 14, 2008, at 1:32 PM, Carl Franks wrote:
> 2008/10/14 Andreas Marienborg <omega at palle.net>:
>>
>> On Oct 13, 2008, at 9:10 PM, Matija Grabnar wrote:
>>
>>> Andreas Marienborg wrote:
>>>>
>>>> Something like that?
>>>>
>>>> If no-one objects, I'll commit it tomorrow
>>>>
>>>>
>>>> - andreas
>>>
>>> That looks very nice, but, if you'll permit me an observation, it
>>> only
>>> covers the part with the rendering of the two forms.
>>>
>>> Would it be possible for you to document the other part of the
>>> usage, too?
>>> (I mean the part where you decide which form was submitted, and
>>> then process
>>> it). It may seem obvious to you, and I **think** I can see how it
>>> would be
>>> done, but having it spelled out would certainly make it easier for
>>> people
>>> who are just coming to catalyst/form-fu.
>>>
>>
>> More like this? this is untested, and written by memory :p someone
>> might
>> wanna write a test-application based on it?
>>
>> - andreas
>>
>>
>>
> Personally, I would set an 'action' for the login form
> ---
> action: __c.uri_for('/login')__
>
> and only check if the login form is submitted in a login() action,
> rather than doing it for every request.
I usually handle it like I did in the example, but an unless ($c-
>user_exists) { } around might be a good idea to not process and auth
every request.
=head2 Multiple forms using Catalyst::Controller::HTML::FormFu
Sometimes you need to display multiple forms on a single page. If you
try to use FormConfig on several actions in a chain, or similar, they
all use $c->stash->{form} to store the form, hence you only get the last
form.
One way to work around such problems is to do a little of the work
yourself:
In this example we have a login_form that we want on every page
# root/forms/login.yml:
---
indicator: username
elements:
-
type: Text
name: username
constraints:
- Required
...
We also have an edit-form
# root/forms/foo/edit.yml
---
indicator: name
elements:
-
type: Text
name: name
constraints:
- Required
-
type: Password
name: password
constraints:
- Required
...
We load this in the top-most auto action:
package MyApp::Controller::Root;
use parent 'Catalyst::Controller::HTML::FormFu';
sub auto : Private {
my ($self, $c) = @_;
# We want to utilize alot of the magic that the controller
# gives us, so therefore we call $self->form like this
my $login_form = $self->form;
$login_form->load_config('forms/login.yml');
# Notice how we put it into another stash var, not 'form'
$c->stash->{login_form} = $login_form;
unless ($c->user_exists) {
$login_form->process();
if ($login_form->submitted_and_valid) {
# Since we set indicator, we should only end up here
if we
# have a username in the form
$c->authenticate({
username => $login_form->field_value('username'),
password => $login_form->field_value('password'),
});
}
}
}
Any other page that wants to load another form, can now do so freely:
package MyApp::Controller::Foo;
sub edit : Local FormConfig {
my ( $self, $c, $id ) = @_;
my $form = $c->stash->{form};
my $item = $c->model('DBIC::Foo')->find($id);
if ($form->submitted_and_valid) {
# Do whatever you want with it :p
$form->model->update($item);
}
}
In the view-land we now have two stash-variables:
root/foo/edit.tt
[% login_form %]
<h2>edit</h2>
[% form %]
More information about the HTML-FormFu
mailing list