SelectFieldWidget uses vocabulary order to display selected items in the edit form (not the field's order). This leads to order being changed accidentally on edit.
To Reproduce
Given: A SelectFieldWidget on a RelationList with a Vocabulary that is sorted by Title
from plone.app.z3cform.widget import SelectFieldWidget
directives.widget("persons", SelectFieldWidget)
persons = RelationList(
title=_(u"Persons"),
description=_("Choose persons that shall be listed for this location."),
required=False,
default=[],
value_type=RelationChoice(vocabulary="my.package.location_persons"),
)
Select (and/or) order selected items: PersonC, PersonB, PersonA
Save
Edit Again
SelectWidget displays: PersonA, PersonB, PersonC
Saving the form (w/o even touching the persons
field will change the order of the
selected items.
Possible Solutions
in archetypes i previously worked around this by returning the correct order in the vocabulary (pseudo-code)
def SortedPersonVocabulary(context)
uids = context.getField('persons').getRaw(context)
persons = catalog(portal_type="Person", sort_on="sortable_title")
_max = len(uids)
def pos(x):
try:
return uids.index(x.UID)
except ValueError:
return _max
return to_vocab(sorted(persons, key=pos))
of course i can use the same workaround again but i strongly believe this should be fixed on widget level
first i'd have suggested to change z3c.form.browser.select.SelectWidget.items
and make items return the selected items in the correct order prior to the rest of the vocabulary values.
def pos(term):
try:
return self.value.index(term.token)
except ValueError:
# keep original pos for all non selected values
return len(self.value)
terms = self.terms
if ISequence.providedBy(self.field) or self.orderable:
terms = sorted(self.terms, key=pos)
for idx, term in enumerate(terms):
addItem(idx, term)
this works, but i'm not sure if a pr like this would be welcomed on zope-level.
browsing through the z3c.form repos i see there is also a OrderedSelectWidget
maybe plone.app.z3cform
SelectFieldWidget
should use this widget instead the plain selectwidget?
i really wonder why this problem did not bite a lot of plone5 users before and exists at all.
to be honest, i'm a bit confused due to the number the different packages involved.
maybe someone more involved in plone.app.z3cform and mockup can shed some light on this.
side note rant: I also tried AjaxSelectWidget with a searchable vocab person_vocab(context, query=None)
or source but ran into the same problems @datar reported in his thread in april 2020. the problem still seems not to be solved.