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
Many, many thanks in advance!
Jens
2008/9/8 Jens Hoffrichter <jens.hof...@gmail.com>: