14 |
14 |
15 from cubicweb.selectors import non_final_entity, match_kwargs, one_line_rset |
15 from cubicweb.selectors import non_final_entity, match_kwargs, one_line_rset |
16 from cubicweb.web import INTERNAL_FIELD_VALUE, eid_param |
16 from cubicweb.web import INTERNAL_FIELD_VALUE, eid_param |
17 from cubicweb.web import form, formwidgets as fwdgs |
17 from cubicweb.web import form, formwidgets as fwdgs |
18 from cubicweb.web.controller import NAV_FORM_PARAMETERS |
18 from cubicweb.web.controller import NAV_FORM_PARAMETERS |
19 from cubicweb.web.formfields import HiddenInitialValueField, StringField |
19 from cubicweb.web.formfields import StringField |
20 |
20 |
21 |
21 |
22 class FieldsForm(form.Form): |
22 class FieldsForm(form.Form): |
23 """base class for fields based forms. |
23 """base class for fields based forms. |
24 |
24 |
277 def form_field_vocabulary(self, field, limit=None): |
277 def form_field_vocabulary(self, field, limit=None): |
278 """return vocabulary for the given field. Should be overriden in |
278 """return vocabulary for the given field. Should be overriden in |
279 specific forms using fields which requires some vocabulary |
279 specific forms using fields which requires some vocabulary |
280 """ |
280 """ |
281 raise NotImplementedError |
281 raise NotImplementedError |
|
282 |
|
283 def form_field_modified(self, field): |
|
284 return field.is_visible() |
282 |
285 |
283 def _field_has_error(self, field): |
286 def _field_has_error(self, field): |
284 """return true if the field has some error in given validation exception |
287 """return true if the field has some error in given validation exception |
285 """ |
288 """ |
286 return self.form_valerror and field.name in self.form_valerror.errors |
289 return self.form_valerror and field.name in self.form_valerror.errors |
472 # important because `vocabfunc` might return a list with |
475 # important because `vocabfunc` might return a list with |
473 # couples (label, None) which act as separators. In these |
476 # couples (label, None) which act as separators. In these |
474 # cases, it doesn't make sense to sort results afterwards. |
477 # cases, it doesn't make sense to sort results afterwards. |
475 return vocabfunc(rtype, limit) |
478 return vocabfunc(rtype, limit) |
476 |
479 |
|
480 def form_field_modified(self, field): |
|
481 if field.is_visible(): |
|
482 # fields not corresponding to an entity attribute / relations |
|
483 # are considered modified |
|
484 if not field.eidparam: |
|
485 return True # XXX |
|
486 try: |
|
487 if field.role == 'subject': |
|
488 previous_value = getattr(self.edited_entity, field.name) |
|
489 else: |
|
490 previous_value = getattr(self.edited_entity, |
|
491 'reverse_%s' % field.name) |
|
492 except AttributeError: |
|
493 # fields with eidparam=True but not corresponding to an actual |
|
494 # attribute or relation |
|
495 return True |
|
496 # if it's a non final relation, we need the eids |
|
497 if isinstance(previous_value, list): |
|
498 # widget should return untyped eids |
|
499 previous_value = set(unicode(e.eid) for e in previous_value) |
|
500 new_value = field.process_form_value(self) |
|
501 if self.edited_entity.has_eid() and (previous_value == new_value): |
|
502 return False # not modified |
|
503 return True |
|
504 return False |
|
505 |
477 def subject_relation_vocabulary(self, rtype, limit=None): |
506 def subject_relation_vocabulary(self, rtype, limit=None): |
478 """defaut vocabulary method for the given relation, looking for |
507 """defaut vocabulary method for the given relation, looking for |
479 relation's object entities (i.e. self is the subject) |
508 relation's object entities (i.e. self is the subject) |
480 """ |
509 """ |
481 entity = self.edited_entity |
510 entity = self.edited_entity |