[ZPT] DRAMA: Can Formulator Play Nicely With ZPT? (Part II)
Jeffrey P Shell
jeffrey@cuemedia.com
Fri, 11 Oct 2002 17:58:45 -0600
First - not the best attitude to have when seeking help.
Second - you would probably have gotten an answer faster on the
zope@zope.org list. There are more people there, and more Formulator
users. ZPT is a fairly focused mailing list. There's even a dedicated
Formulator mailing list which will probably be of better help, which
you can find on the Formulator page on Zope.org
http://www.zope.org/Members/faassen/Formulator
On Friday, October 11, 2002, at 04:20 PM, beno wrote:
> Hi;
> This is my SECOND POST concerning this question. I KNOW someone out
> there has the answer. Hopefully that person will be kind enough to
> help...
>
> I'm trying to follow a recipe someone named *macquyver007* posted on
> zopelabs for using Formulator. (I've done away with his check_form
> script since I'm not interested in authenticating users.) Here's a
> code snippet:
>
> <form name="email_us_formulator" method="post" action="email_us.zpt">
> Your Name:<br>
> <input tal:condition="python:request.has_key('field_Your Name')"
> tal:attributes="value request/field_Your Name" name="field_Your Name"
> type="text" id="field_Your Name">
> <input tal:condition="python:not request.has_key('field_Your
> Name')" name="field_Your Name" type="text" id="field_Your Name">
Alright. Here's what I do with table based forms that I don't let
formulator automatically render. I use a table based form so I can (a)
control layout, and (b) have some nice contexts. If your id's have
spaces in them - you're probably going to have problems.
1.<table tal:define="form here/myFormulatorForm">
2. <tr tal:define="yourname
request/YourName|some_other_data_source/YourName|nothing">
3. <th align="left">Your Name:</th>
4. <td><input type="text" name="YourName"
5. tal:replace="structure
python:form.YourName.render(yourname)">
6. </td>
7. </tr>
8.</table>
On line 1, I make a handy shortcut that I can use in expressions inside
of the table tag.
On line 2, I look for a value to populate the field with, looking first
in the 'request' object (usually populated when doing error handling,
depending on the method used), and then some other data source like a
SQL record or another object, if this form is being used to edit items,
finally setting the value to 'nothing' if those paths fail.
On line 4, I make the input tag. But it could just be a span, could be
any tag really, because I'm going to replace it. I often sketch out my
forms in GoLive first before adding the TAL annotations, and it's
helpful to keep a tag that approximates the output.
Because on line 5, I do a tal:replace structure statement, calling the
render method on the Field 'YourName' which is in the
'myFormulatorForm' object. This lets me use Formulator to decide
details about each field - its size, max length, and other validation
and enforcement settings, and have those get rendered properly at
output time AND dealt with properly at validation time.
Using the code above, I don't have to have two versions of the same tag
- one that responds to whether the request has the value, and one that
doesn't. Formulator will populate the field value with what I pass in
to the 'render' tag, and will handle an empty value fine.
> My problems are these:
> Why doesn't the form validate? How do I make it validate?
If Formulator has the right information (depending on how you either
populate your input tags, or generate them - which is why I use
'tal:replace="structure ..."' - it helps ensure that Formulators
validators get what they want), you can have a Python Script like the
following:
from Products.Formulator.Errors import FormValidationError
request = container.REQUEST
errors = []
try: context.myFormulatorForm.validate_all_to_request(request)
except FormValidationError, e:
errors = e.errors
## You can go through the errors list and build a structure
## like a dictionary to make hilighting error fields easier,
## or you can just loop through the errors in the return
## page to display error fields and the validation messages
## in a single block.
edict = {}
for error in errors:
edict[error.field_id] = error.error_text
if errors:
return context.restrictedTraverse('mytemplate.pt')(
request, errors=errors, edict=edict,
)
else:
## do success handler
> How do I incorporate a textarea? I've tried changing the *input* part
> of the tag, but that simply makes the tag disappear!
There are a couple of different TextArea Formulator Fields.
<input tal:replace="structure python:form.aTextArea.render(value)">
and
<textarea tal:replace="structure python:form.aTextArea.render(value)">
</textarea>
will yield the same results.