Thanks, you've been really helpful. Can I ask a couple of quick 
questions about this? I'll even stick up a trac section on my experience 
for a bit of extra docs in return :-)

I'm a semmantic stickler - what would you recommend is the best way to 
organise this lot in to fieldsets? I put everything apart from submit 
buttons in to fieldsets - provides context. I looked at the FieldSet 
class, the best I can come up with goes something like this:

class AccountFields(widgets.WidgetsDeclaration):
        userId = widgets.TextField()
        password = widgets.PasswordField()
        emailAddress = widgets.TextField()

class PersonalFields(widgets.WidgetsDeclaration):
        displayName = widgets.TextField()
        firstname = widgets.TextField()
        lastname = widgets.TextField()

class RegisterForm(widgets.WidgetsDeclaration):
        account = widgets.FieldSet(legend="Account Information", 
fields=AccountFields())
        personal = widgets.FieldSet(legend="Personal Information", 
fields=PersonalFields())

etc... return dict(form=widgets.TableForm(fields=RegisterForm(), 
submit_text="Register"))

Does that look alright to you?

Cheers

-Rob


Alberto Valverde wrote:
> 
> On 11/03/2006, at 16:04, Robin Haswell wrote:
> 
>> Hey guys
>>
>> I've just started a Turbogears project (.9a1) to see if it really  
>> could
>> help me speed up my web application development (short answer: it
>> didn't). However, I thought it might be useful for me to let you know
>> my thoughts on the form widgets work coming from a PHP developer's  
>> POV.
>>
>> My code was basically this:
>>
>> class RegisterForm(widgets.WidgetsDeclaration):
>>      userId = widgets.TextField("Username")
>>      password = widgets.PasswordField("Password")
>>      emailAddress = widgets.TextField("E-mail address")
>>      displayName = widgets.TextField("What do you like to be called?")
>>      firstname = widgets.TextField("First name")
>>      lastname = widgets.TextField("Last name")
>>
>> and then:
>>
>>      @turbogears.expose(html=".templates.register")
>>      def register(self):
>>              register_form = widgets.TableForm(fields=RegisterForm(),
>> submit_text="Register")
>>              return dict(form=register_form)
>>
>> I'm probably doing it wrong (which is not the point), but intuitively
>> you would expect to get form fields with the name attribute as the
>> RegisterForm members, with the label values as the TextField  
>> parameter.
>> What I got was the label values at the TextField parameter, which  
>> was..
>> wrong. Maybe there's a keyword argument I should have been setting,  
>> but
>> I think the way I thought it should be is the most intuitive way of
>> doing it (by definition, I guess).
> 
> Yep, you just missed the "label" keyword parameter, that would be:
> 
> userId = widgets.TextField(label="Username")
> 
> Regarding RegisterForm, a WidgetsDeclaration is really a normal list  
> but one you can define as a class but with the fields as attributes.  
> example:
> 
>  >>> class MyFields(WidgetsDeclaration):
> ...    name = TextField(label="bbb")
> ...    age = TextField(label="aaa")
> ...
>  >>> MyFields()
> [TextField(name='name', field_class='textfield', attrs={}), TextField 
> (name='age', field_class='textfield', attrs={})]
> 
> With the only difference that the first syntax is much nicer :)
> 
> This is really only a list of fields, they "become" a form as soon as  
> you create instantiate it with your fields:
> 
> TableForm(fields=MyFields())
> 
> 
> 
>> Anyway, now I'm doing it the manual way, which sucks because I have to
>> type "username" five times to get the result I want. As a profession
>> PHP programmer, I know from experience that at least 50% of my time
>> goes in to form generation, collection and validation. If Turbogears
>> really wants to be a RAD tool, this really needs to be sorted out :-/
> 
> This is exactly what the Forms do ;) You can also attach a validator  
> to each of your fields so when the form is submitted your controller  
> gets clean values. Short example:
> 
> class MyFields(WidgetsDeclaration):
>      name = TextField(label="bbb")
>      age = TextField(label="aaa", validator=validators.Int())
> 
> form = TableForm(fields=MyFields())
> 
> @expose(template="X")
> def new_user(self):
>      return dict(form=form, action="save_user")
> 
> @validate(form=form)
> @error_handler(new_user)
> @expose(template="Y")
> def save_user(self, name, age):
>      assert isinstance(age, int)
>      # do something useful...
> 
> Template X contains something like:
> 
> ${form.display(action=action)}
> 
> These few lines of code will:
> 
>   1) display the form to the user when he/she points his/her browser  
> to /new_user
>   2) validate it making sure age is a number and converting it for  
> your app to use
>   3) Redirect the user back to /new_user if validation fails and show  
> nice error messages beside the fields explaining what went wrong and  
> prepopulating it with the vallues he/she had previously filled in.
> 
> This is just a  silly example but you can get the feel of it... It's  
> true that there's a big lack of documentation (formal documentation  
> that is) regarding all this but I hope it will soon be sorted out.
> 
>> Apologies if this is fixed in SVN, I'm not running SVN because I need
>> to keep my environment stable - I'm hoping this project's completion
>> will coincide with the 0.9 release. About 3 months, right?
> 
> SVN has a nice internal cleanup regarding forms/widgets waiting for  
> 0.9a2 :) However, the example I showed you should work fine in .9a1
> 
> Hope it helps,
> Alberto
> 
> 
> 

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"TurboGears" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/turbogears
-~----------~----~----~----~------~----~------~--~---

Reply via email to