Skip to main content

A z3c form keyword widget using select2.

Project description


ftw.keywordwidget provides six features:

  1. A widget, which loads select2 for better usability on single and multiselect fields.

  2. A ChoicePlus field, which allows new terms. This is prevents us from making a specific, complicated source, which allow new items.

  3. Render a additional New Entry textarea for new terms.

  4. Uses tags feature of select 2 to add new keywords.

  5. A async option to get the selectable options with the select2 ajax options.

  6. Custom templates for results and selected items

The widget supports schema.Choice, schema.Tuple and schema.List fields.

Unicode or utf-8??

The ICategorization behavior provided by this package depends on the plone default index “Subject”. In DX “Subject” is a accessor for “subject”, which returns utf-8. “subject” itself has a property getter for “subjects”, where the values are actually stored.

The Plone KeywordsVocabulary builds it’s terms using the catalog value, which is utf-8 in case of the Subject index. By convention indexed values should be always utf-8 and DX values should always be unicode.

This actually means in the case of the KeywordsVocabulary the value needs to be stored as utf-8, because the vocabulary values are encoded as utf-8. The SequenceWidget fieldToWidget converter has a sanity check included, which makes sure only field values, which are also in vocabulary are computed. And this means if you store new terms as unicode values, the whole thing falls apart. Currently the widget makes sure to work perfectly with the “Subject” index, which relays on utf-8 values, which is not common with DX types.

Beside of the primary Use-Case, the widget also supports vocabularies, with unicode values, but this needs to be configured separately on the widget. New terms are than added as unicode instead of utf-8.

directives.widget('unicode_keywords', KeywordFieldWidget, new_terms_as_unicode=True)
unicode_keywords = schema.Tuple(

Async option

The async option can only be used if the source is a IQuerySource from z3c.formwidget.query.interfaces. This interface extends the ISource specification by a search method, which is essential for the async option.

Basically if async=True the select2 Widget asks a search endpoint for possible options by a given search term. Further the search endpoint queries the IContentSourceBinder defined on the field.

directives.widget('async', KeywordFieldWidget, async=True)
async = schema.Tuple(
    title=u'Some async values',

Primary Use-Case

The widget provides the same functionality as the AT Keywordwidget with some benefits.

Features from the AT Widget:

  • Protect adding new terms by a permission/role

  • Display all possible values

  • Add new terms


  • Configurable select2 widget

  • Sane defaults for the Widget

  • z3c.form Widget

  • Based on the SelectWidget (No new converter, etc. needed)

  • Configurable “add new terms permission” per field/widget possible


There are several other z3c form widgets for plone 4.x, which provides a similar feature set, Like collective.z3cform.keywordwidget, or the AutocompleteWidget.

  • They do not fit the primary Use-Case.

Further you can configure the select2 plugin as you wish.


Plone 4.3.x and 5.1.x

Note that Plone 5.1.x uses v3.5 of Select2 whereas this product uses v4.0.2.


  • Add the package to your buildout configuration:

eggs +=

Usage / Integration

This Widget is not automatically applied to all possible select fields. The idea is that you integrate it where needed by your self.

But for the primary Use-Case mentioned above, there is a behavior:

  1. Install the default profile and the select2js profile if needed.

  2. Enable the ftw.keywordwidget.behavior.IKeywordCategorization behavior on your content type.

For some other Use-Cases you can also enable the ftw.keywordwidget.behavior.IKeywordUseCases behavior. This enables a single and multi select field.

Check for examples:

from ftw.keywordwidget.widget import KeywordFieldWidget

class IKeywordUseCases(model.Schema):

    directives.widget('types', KeywordFieldWidget)
    types = schema.List(

    directives.widget('types2', KeywordFieldWidget)
    types2 = schema.Choice(
        title=u'Single type',

alsoProvides(IKeywordUseCases, IFormFieldProvider)

You can configure select2 as you wish by giving a js_config to widget factory.

                  js_config={'placeholder': 'Select something...'})

The select2 4.0.2 JS Plugin is shipped with this package. But you it’s not installed with the default profile, because you may already have a select2 JS installed for other purpose. If you need select2 you can install the ftw.keywordwidget Install select2 jquery plugin profile.


You can define your own templates for each plone-widget or you replace the default widget for all your used keywordwidgets.

First of all, you need to create a new templates (take a look at the select2-documentation to see what a template is in the select2-context). Wrap it into a constructor-function to get access to the widget itself (context-aware).

function myPurpleTemplate(widget) {
    return function(data) {
        return $('<span style="background-color:purple" />').text(data.text);
function myBlueTemplate(widget) {
    return function(data) {
        return $('<span style="background-color:blue" />').text(data.text);

then you need to register it

$(document).on('ftwKeywordWidgetInit', function(e) {
  window.ftwKeywordWidget.registerTemplate('purple', myPurpleTemplate);
  window.ftwKeywordWidget.registerTemplate('blue', myBlueTemplate);

and use it in your desired widgets

directives.widget('colours', KeywordFieldWidget,
colours = schema.Tuple(
    title=u'Some colours',

If you wish to override the default-template, just register a template for

defaultResultTemplate or defaultSelectionTemplate depending on which defaulttemplate you want to override.

function myBlackTemplate(data) {
    return $('<span style="background-color:black" />').text(data.text);

$(document).on('ftwKeywordWidgetInit', function(e) {
  window.ftwKeywordWidget.registerTemplate('defaultResultTemplate', myBlackTemplate);



  1. Fork this repo

  2. Clone your fork

  3. Shell: ln -s development.cfg buidlout.cfg

  4. Shell: python

  5. Shell: bin/buildout

Run bin/test to test your changes.

Or start an instance by running bin/instance fg.


2.2.4 (2021-05-10)

  • Fix invalid initialization, for example on PAM views. [mathias.leimgruber]

2.2.3 (2021-05-03)

  • Make sure the custom focus event does not get triggered on non keywordwifget select2 fields. [mathias.leimgruber]

  • Move Plone 5 upgrade step to the correct folder so it’s picked up by ftw.upgrade [Nachtalb]

2.2.2 (2020-07-23)

  • Stop generating sourcemaps for JavaScript (which isn’t working with Plone). [djowett-ftw]

  • Fix empty select2 widget when initialised too early [Nachtalb]

2.2.1 (2020-05-12)

  • Fix Plone5 JS initialization + Fix loading keywordwidget on tab change. [mathias.leimgruber]

2.2.0 (2019-12-14)

  • Fix product to work on Plone5 in production (resolves #46) [djowett-ftw]

  • Fix on click event for edit form tabs (resolves #42) [djowett-ftw]

2.1.2 (2019-11-12)

  • Explicitly flush collective.indexing queue before building vocabularies to address some race conditions where catalog contents aren’t up-to-date. [lgraf]

2.1.1 (2019-10-17)

  • Make sure terms from KeywordSearchableSource have a title. [njohner]

  • Append changelog to long_description [Nachtalb]

2.1.0 (2019-08-20)

  • Allow to use sources also not in async mode. [njohner]

  • Allow adding new terms in async mode. [njohner]

  • Fix an error where it was no longer possible to add tags after another async widget have been used. [elioschmutz]

2.0.0 (2019-04-18)

  • Add support for Plone 5.1.x. [mbaechtold]

  • Fit newer version of select2 into keywordwidget resources to prevent conflict with an older vers. of select2 required by plone. [mathias.leimgruber, busykoala]

1.5.2 (2018-09-21)

  • Fix french translations. [phgross]

1.5.1 (2018-08-27)

  • Remove improper parent of parent validations from ChoicePlus. [Rotonen]

1.5.0 (2017-12-14)

  • BREAKING CHANGE: Disallow setting a custom permission at widget init time. [Rotonen]

  • Move the accidentally-persisting permission check from the field to the widget and cache the result in the request. [Rotonen]

1.4.2 (2017-11-23)

1.4.1 (2017-11-15)

  • Add event after initializing a widget. [elioschmutz]

1.4.0 (2017-11-14)

  • Add possiblity to add templates for the select2 widget. [elioschmutz]

1.3.6 (2017-08-31)

  • Only add terms to the new field list if it’s really a new selected term. [mathias.leimgruber]

1.3.5 (2017-08-31)

  • Fix a bug, which I introduced in 1.3.3 and miss to catch in 1.3.4 :-( [mathias.leimgruber]

1.3.4 (2017-08-30)

  • Automatically open the search menu for single value fields. [mathias.leimgruber]

  • BugFix: Fix JS error on single value fields. [mathias.leimgruber]

1.3.3 (2017-07-31)

  • BugFix: No longer add items if they’re not “really” selected. [mathias.leimgruber]

1.3.2 (2017-07-11)

  • Removed superfluous for attribute for a behavior without a factory configured. [phgross]

1.3.1 (2017-06-14)

  • Added french translations. [phgross]

  • BugFix: Do not use the value as id in the search endpoint. [mathias.leimgruber]

  • BugFix: Get stored terms by token not by value, since self.value stores the widget value. [mathias.leimgruber]

1.3.0 (2017-05-11)

  • Add testbrowser widget for Keywordwidgets with async option. [mathias.leimgruber]

  • No longer load keywordwidget JS inline in the widget. [mathias.leimgruber]

  • Implement new async option. [mathias.leimgruber]

1.2.0 (2017-04-24)

  • Implement new option to create new terms with unicode values instead of utf-8. [mathias.leimgruber]

1.1.4 (2017-03-20)

  • Always hide new entries field. [mathias.leimgruber]

1.1.3 (2017-03-09)

  • No longer duplicate keywords with non ascii chars. [deiferni]

  • Don’t drop user-input when a form including the widget has validation errors. [deiferni]

  • Fix an issue if the user only inserts one keyword into the widget. [elioschmutz]

  • Fix selec2js profile path to select2 resources. [deiferni]

1.1.2 (2017-03-02)

  • Downgrade select2 from 4.0.3 to 4.0.2 to fix an ie11 issue. See [elioschmutz]

  • Move select2 files into a folder without a version postfix. This makes it much easier to upgrade/downgrade the select2 version without upgradesteps. [elioschmutz]

1.1.1 (2017-02-22)

  • BugFix recarding vocabularies and the tags feature of select2. [mathias.leimgruber]

1.1.0 (2017-02-08)

  • Add i18n helper for translations. [mathias.leimgruber]

  • Implement select2 tag option for adding new keywords. This hides the new keyword textarea. Warning: this is the new default, you can disable it by passing tags: false. [mathias.leimgruber]

1.0.4 (2017-02-07)

  • Add support for schema.Tuple fields. [mathias.leimgruber]

1.0.3 (2016-10-04)

  • Disable compression of the already minified “select2.min.js”. [mbaechtold]

1.0.2 (2016-09-28)

  • Make “add new term permission” configurable + lawgiver support. [mathias.leimgruber]

1.0.1 (2016-09-28)

  • Reinitilize select2 if overlay content is replaced. [mathias.leimgruber]

1.0.0 (2016-09-28)

  • Init Release [mathias.leimgruber]

Project details

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ftw.keywordwidget-2.2.4.tar.gz (188.8 kB view hashes)

Uploaded source

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page