SelectFieldWidget and AjaxSelectFieldWidget in classic UI

There are some similarities to this post SelectFieldWidget breaks sort order of lists - #3 by frisi

The plone.app.z3cform widgets SelectFieldWidget and AjaxSelectFieldWidget are commonly used in Plone, and I have been using them for just about all of my schemas with a Choice field, in lieu of the old in-and-out widget. Judging by the name you might think the only difference is whether or not it's AJAX, and you'd want to maybe use AJAX for big vocabularies and non-AJAX for smaller ones. However there are some bigger differences in their structure that lead to things breaking under different conditions in each.

This package GitHub - imsweb/ims.selectfields: [Ajax]SelectFieldWidget tests is an an attempt to observe these widgets under different conditions, most notably under different vocabularies. Installing this on a Plone 6 site will give you four Dexterity content types using:

  1. A static, SimpleVocabulary instance
  2. A function that provides IVocabularyFactory
  3. A class that implements IVocabularyFactory (call accepts a query parameter)
  4. The StaticCatalogVocabulary from plone.app.vocabularies, as used on a RelationList/Choice field.

There were four different types of behavior that I observed as being problematic:

  1. Searching - typing all or part of the term's value or title should yield just those that match. (In some cases it would return all terms)
  2. Already selected - once a term has been selected it shouldn't appear as an option again. (I had difficulty reproducing problems here, sometimes I would select term "Term1" and it would still be in the drop down, but I was not able to consistently reproduce this)
  3. Ordering - select2 is the basis for these widgets and it lets you drag/drop to order. However in some cases this didn't seem to actually make it into the REQUEST
  4. Existing values on the context - Select a term and hit save. Pull up the edit form again. Options that are saved to the context should display properly. (In some cases it would display the term value, instead of the term title)

Results

Please see the readme GitHub - imsweb/ims.selectfields: [Ajax]SelectFieldWidget tests here for the problems discovered.

Summarization of common findings

  • You almost always want to use a class that implements IVocabularyFactory for the vocabulary. Other, simpler vocabulary types are possible but IMO turn out to have gotchas e.g. it will load and populate a dropdown but searching won't actually work.
  • The Ajax version of the widget appears to have a single <input> with semi-colon separated values while the non-Ajax uses a <select> tag. This is surely related to the ordering issue. If you inspect the DOM, the Ajax version does change the semi-colon separated values for the hidden input, but nothing changes with the select options. The widgets also accept a "seperator" parameter which makes no sense for the non-Ajax widget since it just uses multiple options. The result is that if you want ordering you have to use the Ajax version of the widget
  • I was very interested in the new(ish) StaticCatalogVocabulary as I tend to have a good amount of RelationChoice/List fields where I want a traditional select field to pick up certain content. You can set pattern options with the Relation widget to remove browsing/etc, but this streamlined it and opened up more options like checkboxes/radio/etc. In the case of these two widgets though, you will have to use the non-Ajax select widget and eschew the ability to order selections, because AjaxSelectFieldWidget will not properly display "default" values that come from the current context. I guess if you used this on something like a search form that ignores context it would be fine.

Conclusions
The documentation on using these fields in 6 is not the greatest, but my perception is that updating documentation alone is not going to be enough. It would probably make sense to have SelectFieldWidget work with ordering, as an example. But it would also help to update documentation. From older versions of Plone I have experience with all of these ways of generating vocabularies, but perhaps new docs should recommend only making a class that implements IVocabularyFactory now? There could very well be other methods like Source classes that address some of the issues here (and maybe create new ones!) that I am not familiar with, or maybe pattern options.

I would be very interested if anyone has workarounds to address the problems I found, or has suggestions for other types of sources/vocabulary I can test against.

1 Like

I found that searching can be made to work if you base your vocabulary on a catalog query like this:

    query = request.form.get('query', '') and '%s*' % request.form['query']
    brains = p_catalog(
        path={
            'query': brand_paths,
            'depth': 0,
        },
        Title={'query': query},
    )

That is for the function based implementation of IVocabularyFactory yes? That makes sense.

Yes, correct. Sorry, don't have an example to share without having to cut out a lot of custom stuff.

Some notes:

3 Likes

:tada: Thank you @petschki - this widget also supports pat-depends in EasyForm!!! (jumping for joy)