in reply to Mason design issue.

So let me try understand what is going on.

1) You have a set of web forms that each do some action

2) Foreach action you wrote a mason component to handle the submission.

3) Each form should be capable to do this action in stand alone.

4) Each form can be combined into a general page with other forms so you can create the admin view. But each form has variables that are the same.

5) After executing the action, the portion of the admin that submitted the data should display something in the general page.


You're questions:

1) How to combine the different forms in a container so that each form calls the appropriate component without the names of the attributes clashing?

2) Return to the general page the result of your action?


The solution to problem 1:

Create a small java script that you include in every page (using a dhandler for example):

function perform_action(link,form_handled) { var form=document.forms[form_handled]; form.action=link; form.submit(); }

In each web form, name each form in the form tag:

<form method="post" name="<% $form_name %>"> ... </form>

For each button on your page, define now the form and the path to your component for each web form:

<button type=button onclick="perform_action('<% component_path %>' +,'<% $form_name>%')">submit</button>

By naming your forms in the web page, you can use a small javascript to select the correct one by name and submit the data. The name clash disappears because each attribute is unique in each form.

This is also usable when only one form is needed on a page. So you don't have to include ugly 'if-else' structures in your mason code for your web forms to handle the different cases. The javascript is quite light and i didn't had any compatibility problems with it.

Because each web form has an unique name and his proper link to his component, only the specified component is called. Be aware, the mason component doesn't know yet from where it is called. He can distinguish the call from the single web form from the call of the general page.


Still to do, problem2: display the result in the admin console instead. Or make the component known from where it is called.

Solution to this depends on the general architecture of your application. If you have a MVC architecture, the controller can take care of that part. If not, I recommend hidden fields. It isn't that ugly and will solve your problem quickly.


I hope this shed some light, otherwise, feel free to specify more in detail what your problem is.

Replies are listed 'Best First'.
Re^2: Mason design issue.
by EvanCarroll (Chaplain) on Oct 12, 2005 at 07:15 UTC
    To expand on one each form is itself a file component. I am staunchly against javascript and I could accomplish the same thing essentially because each form is unique with a name=<% $m->current_comp->name %>

    Code speaks a thousand words, let me show you the solution the I came up with to add closure to this problem, btw I did add a hidden form field.

    <%attr> http_title =>'Admin Widget' widget_title =>'Change Password' </%attr> <div class="window"> <div class="title"> <% $title %> </div> <div class="body"> <form method="post" action="<% $m->caller(0)->name %>"> <table style="width:100%"> <tr> <td style="width:50%"> New Password: <input type="password" name="password" size +="30" /> </td> <td> Confirm Password: <input type="password" name="password_c +onfirm" size="30" /> </td> </tr> <tr> <td colspan="2"> <input type="hidden" name="form" value="<% $m->current_com +p->name %>" /> <input type="submit" value="Change my Password" /> </td> </tr> </table> </form> </div> </div> <%init> if ( $form eq $m->current_comp->name ) { if ( defined $password && defined $password_confirm ) { if ( $password eq $password_confirm ) { $dbh->do( qq{UPDATE users SET "password" = ? WHERE "pkid" = ? +}, {}, sha1_base64($password), $S->{'pkid'} ); $title .= " || You have changed your password.", print $S->{pk +id}; } else { $title .= " || Passwords do not match."; } } else { $title .= " || Not enough information."; } } </%init> <%shared> use Digest::SHA1 q/sha1_base64/; my $title = $m->current_comp->attr('widget_title'); </%shared> <%args> $S $password_confirm => $m->caller_args(1)->{'password'} || undef $password => $m->caller_args(1)->{'password_confirm'} || u +ndef $form => $m->caller_args(1)->{'form'} || undef </%args>


    This is just a sample, and I plan on writing a serious mason tutorial on alot of the concepts I employ in the frameworks I have made.

    $S is the session data sent from the autohandler.

    the other caller ($password_confirm, $password, $form) args come from what ever serves as the console.

    <% $m->caller(0)->name %>allows me to dynamically target the component for posting (though this works with limited success)
    Take notice to if ( $form eq $m->current_comp->name ) dynamic again.

    I still need to fix it up but have a deadline of monday so I'll play with it later.


    Evan Carroll
    www.EvanCarroll.com