[Zope] form question

jpenny@universal-fasteners.com jpenny@universal-fasteners.com
Tue, 23 Jan 2001 11:58:06 -0500


On Mon, Jan 22, 2001 at 07:55:28PM +0100, Dieter Maurer wrote:
> Oliver Vecernik writes:
>  > I'm designing an application gathering data with forms. Navigation
>  > should be done with Prev and Next buttons. As long as I'm not leaving
>  > the form data should be entered, processed and the *same* or another
>  > form should be displayed, depending on input of the user.
>  > 
>  > So far I'm able to gather data, store them in a database, but can
>  > anybody give me a clue or point me to some docs how to control which
>  > form should be displayed next? It should depend on users input of let's
>  > say a text field.
> Look for the "RESPONSE.redirect" method.
> 
> 
> Dieter

Dieter, as usual, gave a good succinct answer.  But in this case, I
think that the problem is in the way the question is framed, and not
the answer.

I am going to give a completely different answer, based on what I think
the original questioner really needed, it will be a bit long.

I am assuming that the application lays in a folder called MyApplication.

I am going to use a particular coding style that I call "going nowhere",
it is actually a state machine.  I am going to use hidden variables to
hold state, you can also use cookies, database connections or other
mechanisms.

index_html is just a chain of if statements that encode what to
display next.

For example:

<dtml-if "not REQUEST.has_key('current_state')">
  <dtml-var entry_form>
<dtml-elif "current_state=='process_entry' and action=='Next'">
  <dtml-var next_form>
<dtml-elif "current_state=='next_entry' and action=='Prev'">
  <dtml-var entry_form>
.
.
.
</dtml-if>

entry_form looks like

<form action=. method=post>
  <input type=hidden name=current_state value="process_entry">
  <input type=text size=15 name=my_variable>
  <input type=submit name=action value="Next">
</form>

(This is where the "going nowhere" comes from.  All forms use
. as the action, so the browser never goes to another folder.)

Now, it should be easy to see how to modify index_html to handle
displaying a different form depending on the previous input.
Just put in in one of the tests.

-----------------------------------------------------------------

To elaborate this just a bit, I also typically do an error_entry__form 
that looks like:

<form action=. method=post>
  <font color = red><dtml-var error_message></font>
  <input type=hidden name=current_state value="process_entry">
  <input type=text size=15 name=my_variable value="<dtml-var my_variable>">
  <input type=submit name=action value="Next">
</form>

and change my index_html to look like:

<dtml-if "not REQUEST.has_key('current_state')">
  <dtml-var entry_form>
<dtml-elif "current_state=='process_entry' and action=='Next'">
  <dtml-var handle_process_entry_next>
<dtml-elif "current_state=='next_entry' and action=='Prev'">
  <dtml-var handle_process_entry_prev>
.
.
.
</dtml-if>

Then 

handle_process_entry_next looks like:

<dtml-call "REQUEST.set('error_message', '')">
<dtml-call canonify_process_entry_next_data>
<dtml-call check_process_next_errors>
<dtml-if "error_message != ''">
  <dtml-var error_entry_form>
<dtml-else>
  <dtml-var next_form>
</dtml-if>

(canonify_... does approriate things like stripping, converting to a particular
case, etc.; check_... enforces data consistency conditions.)

  
This is not an original idea.  I saw it when I was pretty green, myself, and
really did not understand its attraction and power.  Here are what I now see
as the benefits.  All of the application is kept in a single folder.  The
index_html is boilerplate, essentially a single long if-statement.  The
canonify_ and check_ methods are likely to be very small also, and can be
implemented in any language.  The forms are essentially pure HTML, and can
be kept very simple (OK, the error_form has a smattering of very simple
DTML to reset the last value of the user's input).  Error handling is natural
and easy to do.  You do not have to redirect.
Redirection destroys your REQUEST, forcing you to do other things to hold
information.

The cost, only that an application's folder gets to be somewhat large.

Jim Penny

> 
> _______________________________________________
> Zope maillist  -  Zope@zope.org
> http://lists.zope.org/mailman/listinfo/zope
> **   No cross posts or HTML encoding!  **
> (Related lists - 
>  http://lists.zope.org/mailman/listinfo/zope-announce
>  http://lists.zope.org/mailman/listinfo/zope-dev )
>