73 # deleting validation errors here breaks form reloading (errors are |
73 # deleting validation errors here breaks form reloading (errors are |
74 # no more available), they have to be deleted by application's publish |
74 # no more available), they have to be deleted by application's publish |
75 # method on successful commit |
75 # method on successful commit |
76 forminfo = self.req.get_session_data(sessionkey, pop=True) |
76 forminfo = self.req.get_session_data(sessionkey, pop=True) |
77 if forminfo: |
77 if forminfo: |
78 self.req.data['formvalues'] = forminfo['values'] |
78 # XXX remove req.data assigment once cw.web.widget is killed |
79 self.req.data['formerrors'] = errex = forminfo['errors'] |
79 self.req.data['formvalues'] = self.form_previous_values = forminfo['values'] |
80 self.req.data['displayederrors'] = set() |
80 self.req.data['formerrors'] = self.form_valerror = forminfo['errors'] |
|
81 self.req.data['displayederrors'] = self.form_displayed_errors = set() |
81 # if some validation error occured on entity creation, we have to |
82 # if some validation error occured on entity creation, we have to |
82 # get the original variable name from its attributed eid |
83 # get the original variable name from its attributed eid |
83 foreid = errex.entity |
84 foreid = self.form_valerror.entity |
84 for var, eid in forminfo['eidmap'].items(): |
85 for var, eid in forminfo['eidmap'].items(): |
85 if foreid == eid: |
86 if foreid == eid: |
86 errex.eid = var |
87 self.form_valerror.eid = var |
87 break |
88 break |
88 else: |
89 else: |
89 errex.eid = foreid |
90 self.form_valerror.eid = foreid |
|
91 else: |
|
92 self.form_previous_values = {} |
|
93 self.form_valerror = None |
90 |
94 |
91 # XXX deprecated with new form system. Should disappear |
95 # XXX deprecated with new form system. Should disappear |
92 |
96 |
93 domid = 'entityForm' |
97 domid = 'entityForm' |
94 category = 'form' |
98 category = 'form' |
164 def error_message(self): |
168 def error_message(self): |
165 """return formatted error message |
169 """return formatted error message |
166 |
170 |
167 This method should be called once inlined field errors has been consumed |
171 This method should be called once inlined field errors has been consumed |
168 """ |
172 """ |
169 errex = self.req.data.get('formerrors') |
173 errex = self.req.data.get('formerrors') or self.form_valerror |
170 # get extra errors |
174 # get extra errors |
171 if errex is not None: |
175 if errex is not None: |
172 errormsg = self.req._('please correct the following errors:') |
176 errormsg = self.req._('please correct the following errors:') |
173 displayed = self.req.data['displayederrors'] |
177 displayed = self.req.data.get('displayederrors') or self.form_displayed_errors |
174 errors = sorted((field, err) for field, err in errex.errors.items() |
178 errors = sorted((field, err) for field, err in errex.errors.items() |
175 if not field in displayed) |
179 if not field in displayed) |
176 if errors: |
180 if errors: |
177 if len(errors) > 1: |
181 if len(errors) > 1: |
178 templstr = '<li>%s</li>\n' |
182 templstr = '<li>%s</li>\n' |
331 |
335 |
332 rendervalues is an optional dictionary containing extra kwargs given to |
336 rendervalues is an optional dictionary containing extra kwargs given to |
333 form_render() |
337 form_render() |
334 """ |
338 """ |
335 self.context = context = {} |
339 self.context = context = {} |
336 # on validation error, we get a dictionary of previously submitted |
|
337 # values |
|
338 self._previous_values = self.req.data.get('formvalues', {}) |
|
339 # ensure rendervalues is a dict |
340 # ensure rendervalues is a dict |
340 if rendervalues is None: |
341 if rendervalues is None: |
341 rendervalues = {} |
342 rendervalues = {} |
342 for field in self.fields: |
343 for field in self.fields: |
343 for field in field.actual_fields(self): |
344 for field in field.actual_fields(self): |
359 |
360 |
360 values found in 1. and 2. are expected te be already some 'display' |
361 values found in 1. and 2. are expected te be already some 'display' |
361 value while those found in 3. and 4. are expected to be correctly typed. |
362 value while those found in 3. and 4. are expected to be correctly typed. |
362 """ |
363 """ |
363 qname = self.form_field_name(field) |
364 qname = self.form_field_name(field) |
364 if qname in self._previous_values: |
365 if qname in self.form_previous_values: |
365 value = self._previous_values[qname] |
366 value = self.form_previous_values[qname] |
366 elif qname in self.req.form: |
367 elif qname in self.req.form: |
367 value = self.req.form[qname] |
368 value = self.req.form[qname] |
368 else: |
369 else: |
369 if field.name in rendervalues: |
370 if field.name in rendervalues: |
370 value = rendervalues[field.name] |
371 value = rendervalues[field.name] |
383 value = value(self) |
384 value = value(self) |
384 return value |
385 return value |
385 |
386 |
386 def form_field_error(self, field): |
387 def form_field_error(self, field): |
387 """return validation error for widget's field, if any""" |
388 """return validation error for widget's field, if any""" |
388 errex = self.req.data.get('formerrors') |
389 if self._field_has_error(field): |
389 if errex and self._errex_match_field(errex, field): |
390 self.form_displayed_errors.add(field.name) |
390 self.req.data['displayederrors'].add(field.name) |
391 return u'<span class="error">%s</span>' % self.form_valerror.errors[field.name] |
391 return u'<span class="error">%s</span>' % errex.errors[field.name] |
|
392 return u'' |
392 return u'' |
393 |
393 |
394 def form_field_format(self, field): |
394 def form_field_format(self, field): |
395 """return MIME type used for the given (text or bytes) field""" |
395 """return MIME type used for the given (text or bytes) field""" |
396 return self.req.property_value('ui.default-text-format') |
396 return self.req.property_value('ui.default-text-format') |
411 """return vocabulary for the given field. Should be overriden in |
411 """return vocabulary for the given field. Should be overriden in |
412 specific forms using fields which requires some vocabulary |
412 specific forms using fields which requires some vocabulary |
413 """ |
413 """ |
414 raise NotImplementedError |
414 raise NotImplementedError |
415 |
415 |
416 def _errex_match_field(self, errex, field): |
416 def _field_has_error(self, field): |
417 """return true if the field has some error in given validation exception |
417 """return true if the field has some error in given validation exception |
418 """ |
418 """ |
419 return field.name in errex.errors |
419 return self.form_valerror and field.name in self.form_valerror.errors |
420 |
420 |
421 |
421 |
422 class EntityFieldsForm(FieldsForm): |
422 class EntityFieldsForm(FieldsForm): |
423 __select__ = (match_kwargs('entity') | (one_line_rset & non_final_entity())) |
423 __select__ = (match_kwargs('entity') | (one_line_rset & non_final_entity())) |
424 |
424 |
441 self.form_add_hidden('__message', msg) |
441 self.form_add_hidden('__message', msg) |
442 # in case of direct instanciation |
442 # in case of direct instanciation |
443 self.schema = self.edited_entity.schema |
443 self.schema = self.edited_entity.schema |
444 self.vreg = self.edited_entity.vreg |
444 self.vreg = self.edited_entity.vreg |
445 |
445 |
446 def _errex_match_field(self, errex, field): |
446 def _field_has_error(self, field): |
447 """return true if the field has some error in given validation exception |
447 """return true if the field has some error in given validation exception |
448 """ |
448 """ |
449 return errex.eid == self.edited_entity.eid and field.name in errex.errors |
449 return super(EntityFieldsForm, self)._field_has_error(field) \ |
|
450 and self.form_valerror.eid == self.edited_entity.eid |
450 |
451 |
451 def _relation_vocabulary(self, rtype, targettype, role, |
452 def _relation_vocabulary(self, rtype, targettype, role, |
452 limit=None, done=None): |
453 limit=None, done=None): |
453 """return unrelated entities for a given relation and target entity type |
454 """return unrelated entities for a given relation and target entity type |
454 for use in vocabulary |
455 for use in vocabulary |