views:

698

answers:

1

Question:

How do I prefill a CheckBoxTable from ToscaWidgets with values.

Background:

I've looked everywhere and I can't seem to figure out how to initialize a particular form field with ToscaWidgets. Most form fields seem to respond just fine to initialization, like if I create a form with a single TextField in it when I render the form in the template and pass in fieldValue=x where fieldValue is the name of the TextField and x is some string the TextField will be filled with x. My problem is with all multiple select field, in particular CheckBoxTable. No matter what I pass in it will not initialize the multiple select. Here is an example of what I'm talking about, it's a user edit page with a CheckBoxTable for groups so you can select several or no groups out of a list of several groups fetched from the databse:

What I have:

My widget is:

from tw import forms
class UserForm(forms.TableForm):

    show_errors = True
    submit_text = "Create User"

    clientOptions = [(-1, "Select a Client")]
    groupOptions = [(-1, "Select a Group")]

    fields = [forms.TextField('name', label_text='User Name', validator=String(not_empty=True), size=40),
              forms.Spacer(),
              forms.SingleSelectField('clientID', label_text='Client Name', validator=Int(min=0), options=clientOptions),
              forms.Spacer(),
              forms.CheckBoxTable('groups', lable_text='Groups', validator=Set(), options=groupOptions, num_cols=3),
              forms.Spacer(),
              forms.PasswordField('password', label_text="Password", validator=String(not_empty=True, min=6), size=40),
              forms.PasswordField('passwordAgain', label_text="Repeat Password", validator=String(not_empty=True, min=6), size=40),
              forms.HiddenField('id')]

editUserForm = UserForm("createUserForm", action='alterUser', submit_text="Edit User")

In my controller I have:

result = model.DBSession.query(model.User).filter_by(id=kw['id']).first()
tmpl_context.form = editUserForm
clientOptions=model.DBSession.query(model.Client.id, model.Client.name)
groupOptions=model.DBSession.query(model.Group.id, model.Group.name)
formChildArgs = dict(clientID=dict(options=clientOptions), groups=dict(options=groupOptions))

userAttributes=dict(id=result.id, name=result.name, groups=[g.id for g in result.groups], clientID=result.clientID, password=result.password, passwordAgain=result.password)

return dict(verb="Edit", modelName = "User", modelAttributes=userAttributes, formChildArgs=formChildArgs, page='editUser')

and in my template (Mako) I have:

${tmpl_context.form(modelAttributes, child_args=formChildArgs) | n}

What I've tried:

In my userAttributs dictionary I've tried:

groups=[g.id for g in result.groups]
groups=[g.name for g in result.groups]
groups=[(g.id, g.name) for g in result.groups]
groups=[[g.id, g.name) for g in result.groups]
groups=result.groups

What I get:

The result of all of this code is a User edit form with data pre-filled with the user data except for the CheckBoxTable. The CheckBoxTable has all of the groups in my database displaying and empty, what I need for for them to be displaying but have the groups the user is apart of checked. I thought the code in the model attributes would do this, since that's what it does for every other field, but there must be some fundamental thing I'm missing about CheckBoxTable instantiation.

Specs:

I'm using Turbogears 2 with ToscaWidgets 0.9.7 forms and Mako for templating.

+1  A: 

set them via the value param.

import tw.forms
f = tw.forms.TableForm(fields=[tw.forms.CheckBoxTable("name",options=(("foo"),("bar")))]) 
f(value={"name":{"foo":True,"bar":False}})
>>> u'<form xmlns="http://www.w3.org/1999/xhtml" action="" method="post" class="tableform">\n    <table border="0" cellspacing="0" cellpadding="2">\n<tr id="name.container" class="even" title="">\n            <td class="labelcol">\n                <label id="name.label" for="name" class="fieldlabel">Name</label>\n            </td>\n            <td class="fieldcol">\n                <table id="name" class="checkboxtable">\n    <tbody>\n    <tr>\n        <td>\n
    <input id="name_0" value="foo" name="name" type="checkbox" checked="checked" />\n            <label for="name_0">foo</label>\n        </td>\n    </tr><tr>\n        <td>\n            <input id="name_1" value="bar" name="name" type="checkbox" />\n            <label for="name_1">bar</label>\n        </td>\n    </tr>\n
</tbody>\n</table>\n            </td>\n        </tr><tr id="submit.container" class="odd" title="">\n            <td class="labelcol">\n            </td>\n
       <td class="fieldcol">\n                <input type="submit" class="submitbutton" value="Submit" />\n            </td>\n        </tr>\n    </table>\n</form>'
Tom Willis
Well I'm already doing this manually in the controller. My problem isn't that the options aren't showing up. In the code above I get a table of checkboxes with all the groups I have defined in my database, I just can't get the ones that are set for that user to be checked. Unless of course you think that by make my form completely data driven it'll solve my initialization issue as well.
Robbie
OH sorry, I misunderstood the question. Typically you pass field values in the value param. I'll edit my answer in a minute
Tom Willis
I love you <3_______ So I tried what you said and it didn't work forever. But I slowly started removing things from my form and found out that setting my validator for that Input to Set() was breaking it. I'll probably let the Tosca guys know about it and maybe they can sort out WTF. Anyway thanks so much.
Robbie
Yeah tw can be a pain once in a while. I tend to just use it for html generation and try to keep everything else out of it for fear of things like a validator causing weird behavior. Though the docs may be hard to navigate, don't hesitate to open up the interpreter and experiment. Sometimes that's the best way. Good luck
Tom Willis