Validating a nested form

7 views
Skip to first unread message

Jens Hoffrichter

unread,
Sep 8, 2008, 3:37:54 PM9/8/08
to toscawidge...@googlegroups.com
Hello all,

I'm having a problem propagating an error in a nested form.

I have build an own ToscaWidget called "CascadedSelector", which
basically just contains a series of select boxes where the next one is
only shown when something is picked in the prior one, and the values
for the just shown select box are queried by Ajax from the
application.

Basically it is used for a three step region selection. The widget is
nothing fancy, just some added calls to JS in the function, mainly it
is still the list_fieldset.mak template, but I include it here for
reference:

--- cascadedselector.mak ---

<%namespace name="tw" module="tw.core.mako_util" />\
<fieldset ${tw.attrs([
("id", context.get("id")),
("class", css_class), ],
attrs = attrs)}>
<%
error = context.get('error')
fieldlist = []
valuelist = []
for i, field in enumerate(fields):
fieldlist.append( (field.id, value_for(field)) )
lastid = None
valuestosetstr = '[ ' + ",".join(map(lambda x: '["%s","%s"]' %
(x[0],x[1]), fieldlist)) + ' ]'
%>
<ul class="cascadedselectorfieldset">

% for i, field in enumerate(fields):
<%
if i < len(fieldlist) -1:
subfields = '[ %s ]' % ",".join(map(lambda x: '"%s"' % x[0],
fieldlist[i+1:]))
field.attrs["onchange"] =
'cs_updateselector("%s","%s","%s","%s",%s)' %
(updateurl,field.id,field.name,fieldlist[i+1][0],subfields)

listyle = ''
if i!=0 and not value_for(field):
listyle = "visibility: hidden;"
%>
<li id="${field.id}_container" style="${listyle}">
<label ${tw.attrs(
[('id', '%s_label' % field.id),
('for', field.id),
('class', 'fieldlabel'),
]
)}>${tw.content(field.label_text)}</label>
<%
args = args_for(field)
if hasattr(field,'options'):
if not field.options:
args["options"] = [ ("","---") ]
error = error_for(field)
%>
${field.display('', **args)}
% if show_children_errors and error and not field.show_error:
<span class="fielderror">${tw.content(error)}</span>
% endif
</li>
% endfor
</ul>
</fieldset>
<script type="text/javascript">
cs_valuestoset = ${valuestosetstr}
f = $('${fieldlist[0][0]}');
if(f.onchange)
{
f.onchange();
}
</script>

--- snip ---

Somehow the error doesn't get propagated correctly to the for, both
error and the error_for(field) are empty here in my example.

This is the definition for the RegionSelectorHousing (the widget I try
to propagate the error to):

class RegionSelectorHousing(tp.CascadedSelectorBox):
class fields(WidgetsList):

country = forms.SingleSelectField(options = countryoptions,
label_text = lazy_gettext("Country"))
subdivision = forms.SingleSelectField(label_text =
lazy_gettext("Subdivision"))
region = forms.SingleSelectField(label_text = lazy_gettext("Region"))

id = "regionselector"
updateurl = h.url_for(controller = "ajax", action = "regionselector")

The updateurl is the parameter for the cascadedselector where the
widget will get it subsequent options.

The form is definied like this:

class EnterHousing(forms.ListForm):
class fields(WidgetsList):
region = RegionSelectorHousing(show_children_errors = True,
show_errors = True)
type = forms.SingleSelectField(options = housing_options,
label_text = lazy_gettext("Type"), validator = v.NotEmpty())
datefrom = forms.CalendarDatePicker(label_text =
lazy_gettext("From"), date_format = '%d.%m.%Y', calendar_lang =
session.get("lang","en"), not_empty = True, validator =
v.All(v.DateTimeConverter(format='%d.%m.%Y', messages = e.base),
v.NotEmpty()))
dateuntil = forms.CalendarDatePicker(label_text =
lazy_gettext("Until"), date_format = '%d.%m.%Y', calendar_lang =
session.get("lang","en"), not_empty = True, validator =
v.All(v.DateTimeConverter(format='%d.%m.%Y', messages = e.base),
v.NotEmpty()))
remarks = RTEBBCode(label_text = lazy_gettext("Remarks"))
validator = qv.RegionSelectorHousing()

enterhousing = EnterHousing("posthousing",css_class = "form_default",
show_children_errors = True, show_errors = True)

The validator has the following code:

class RegionSelectorHousing(FormValidator):
def validate_python(self, value, state):
if not value.has_key("region.country") or not value["region.country"]:
raise Invalid(countryemptymsg, value, state, error_dict = {
"region.country": countryemptymsg})

return value

And I see that the field obviously gets some hint about that an error
occurs, as it has a red border, but I can't figure out how to get the
error message to display it alongside the actual field, so the user
will know what is going on....

Any hints there what I'm doing wrong?

Thanks in advance,
Jens

Jens Hoffrichter

unread,
Sep 19, 2008, 1:53:41 PM9/19/08
to toscawidge...@googlegroups.com
I'm sorry to give this problem basically just a "bump", but it is
getting kind of urgent for me (we are nearing production readiness
with the application the error is occurring in), so ANY hints would be
very much appreciated, as I still haven't found a way to tackle this
problem.

Many, many thanks in advance!

Jens

2008/9/8 Jens Hoffrichter <jens.hof...@gmail.com>:

Reply all
Reply to author
Forward
0 new messages