+ +
+

Select2 4.0.0

+ +

+ The 4.0 release of Select2 is the result of three years of working on the + code base and watching where it needs to go. At the core, it is a full + rewrite that addresses many of the extensibility and usability problems + that could not be addressed in previous versions. +

+ +

+ This release contains many breaking changes, but easy-upgrade paths have + been created as well as helper modules that will allow for backwards + compatibility to be maintained with past versions of Select2. Upgrading + will require you to read the release notes carefully, but the + migration path should be relatively straightforward. You can view a list + of the most common changes that you will need to make + in the release notes. +

+ +

+ Below is an in-depth review of what is new in Select2, as well as some of + the major changes that have been made. +

+
+ +
+

New features

+ +

+ The notable features of this new release include: +

+ +
    +
  • + A more flexible plugin framework that allows you to override Select2 to + behave exactly how you want it to. +
  • +
  • + Consistency with standard <select> elements for all + data adapters, removing the need for hidden <input> + elements. +
  • +
  • + A new build system that uses AMD to keep everything organized. +
  • +
  • + Less specific selectors allowing for Select2 to be styled to fit the + rest of your application. +
  • +
+
+ +
+

Plugin system

+ +

+ Select2 now provides interfaces that allow for it to be easily extended, + allowing for anyone to create a plugin that changes the way Select2 works. + This is the result of Select2 being broken into four distinct sections, + each of which can be extended and used together to create your unique + Select2. +

+ +

+ The adapters implement a consistent interface that is documented in the + options section for adapters, allowing + you to customize Select2 to do exactly what you are looking for. Select2 + is designed such that you can mix and match plugins, with most of the core + options being built as decorators that wrap the standard adapters. +

+
+ +
+

AMD-based build system

+ +

+ Select2 now uses an + AMD-based build system, + allowing for builds that only require the parts of Select2 that you need. + While a custom build system has not yet been created, Select2 is open + source and will gladly accept a pull request for one. +

+ +

+ Select2 includes the minimal almond + AMD loader, but a custom select2.amd.js build is available + if you already use an AMD loader. The code base (available in the + src directory) also uses AMD, allowing you to include Select2 + in your own build system and generate your own builds alongside your + existing infrastructure. +

+ +

+ The AMD methods used by Select2 are available as + jQuery.fn.select2.amd.define()/require(), allowing you to use the + included almond loader. These methods are primarily used by the + translations, but they are the recommended way to access custom modules + that Select2 provides. +

+
+ +
+

Migrating from Select2 3.5

+ +

+ There are a few breaking changes that migrators should be aware of when + they are coming from older versions of Select2. +

+ +

+ If you use the full build of Select2 (select2.full.js), you + will be automatically notified of the major breaking changes, and + compatibility modules will be used in some cases to ensure that your code + still behaves how you were expecting. +

+ +

No more hidden input tags

+ +

+ In past versions of Select2, an <input type="hidden" /> + tag was recommended if you wanted to do anything advanced with Select2, + such as work with remote data sources or allow users to add their own + tags. This had the unfortunate side-effect of servers not receiving the + data from Select2 as an array, like a standard <select> + element does, but instead sending a string containing the comma-separated + strings. The code base ended up being littered with special cases for the + hidden input, and libraries using Select2 had to work around the + differences it caused. +

+ +

+ In Select2 4.0, the <select> element supports all core + options, and support for the old + <input type="hidden" /> has been deprecated. This means + that if you previously declared an AJAX field with some pre-selected + options that looked like… +

+ +{% highlight html linenos %} + +{% endhighlight %} + +

+ It will need to be recreated as a <select> element with + some <option> tags that have value + attributes that match the old value. +

+ +{% highlight html linenos %} + +{% endhighlight %} + +

+ The options that you create should have selected="selected" + set so Select2 and the browser knows that they should be selected. The + value attribute of the option should also be set to the value + that will be returned from the server for the result, so Select2 can + highlight it as selected in the dropdown. The text within the option + should also reflect the value that should be displayed by default for the + option. +

+ +

Advanced matching of searches

+ +

+ In past versions of Select2, when matching search terms to individual + options, which limited the control that you had when displaying results, + especially in cases where there was nested data. The matcher + function was only given the individual option, even if it was a nested + options, without any context. +

+ +

+ With the new matcher function, only the root-level options are matched and + matchers are expected to limit the results of any children options that + they contain. This allows developers to customize how options within + groups can be displayed, and modify how the results are returned. +

+ +

+ A function has been created that allows old-style matcher functions to be + converted to the new style. You can retrieve the function from the + select2/compat/matcher module, which should just wrap the old + matcher function. +

+ +

+ So if your old code used a matcher that only displayed options if they + started with the term that was entered, it would look something like… +

+ +{% highlight js linenos %} +function matchStart (term, text) { + if (text.toUpperCase().indexOf(term.toUpperCase()) == 0) { + return true; + } + + return false; +} + +$("select").select2({ + matcher: matchStart +}) +{% endhighlight %} + +

+ Then in Select2 4.0, you would need to wrap the matchStart + method (or the name of the matcher you created) with a + oldMatcher method that we have created. +

+ +{% highlight js linenos %} +function matchStart (term, text) { + if (text.toUpperCase().indexOf(term.toUpperCase()) == 0) { + return true; + } + + return false; +} + +$.fn.select2.amd.require(['select2/compat/matcher'], function (oldMatcher) { + $("select").select2({ + matcher: oldMatcher(matchStart) + }) +}); +{% endhighlight %} + +

+ This will work for any matchers that only took in the search term and the + text of the option as parameters. If your matcher relied on the third + parameter containing the jQuery element representing the original + <option> tag, then you may need to slightly change + your matcher to expect the full JavaScript data object being passed in + instead. You can still retrieve the jQuery element from the data object + using the data.element property. +

+ +

More flexible placeholders

+ +

+ In the most recent versions of Select2, placeholders could only be + applied to the first (typically the default) option in a + <select> if it was blank. The + placeholderOption option was added to Select2 to allow users + using the select tag to select a different option, typically + an automatically generated option with a different value. +

+ +

+ The placeholder option can now take an object as well as just + a string. This replaces the need for the old + placeholderOption, as now the id of the object + can be set to the value attribute of the + <option> tag. +

+ +

+ For a select that looks like the following, where the first option (with a + value of -1) is the placeholder option… +

+ +{% highlight html linenos %} + +{% endhighlight %} + +

+ You would have previously had to get the placeholder option through the + placeholderOption, but now you can do it through the + placeholder option by setting an id. +

+ +{% highlight js linenos %} +$("select").select2({ + placeholder: { + id: "-1", + placeholder: "Select an option" + } +}) +{% endhighlight %} + +

+ And Select2 will automatically display the placeholder when the value of + the select is -1, which it will be by default. This does not + break the old functionality of Select2 where the placeholder option was + blank by default. +

+ +

Display reflects the actual order of the values

+ +

+ In past versions of Select2, choices were displayed in the order that + they were selected. In cases where Select2 was used on a + <select> element, the order that the server received + the selections did not always match the order that the choices were + displayed, resulting in confusion in situations where the order is + important. +

+ +

+ Select2 will now order selected choices in the same order that will be + sent to the server. +

+ +

Changed method and option names

+ +

+ When designing the future option set for Select2 4.0, special care was + taken to ensure that the most commonly used options were brought over. + For the most part, the commonly used options of Select2 can still be + referenced under their previous names, but there were some changes which + have been noted. +

+ +

+ Removed the requirement of initSelection +

+ +

+ In the past, whenever you wanted to use a custom data adapter, such as + AJAX or tagging, you needed to help Select2 out in determining the initial + values that were selected. This was typically done through the + initSelection option, which took the underlying data of the + input and converted it into data objects that Select2 could use. +

+ +

+ This is now handled by + the data adapter in the + current method, which allows Select2 to convert the currently + selected values into data objects that can be displayed. The default + implementation converts the text and value of option elements + into data objects, and is probably suitable for most cases. An example of + the old initSelection option is included below, which + converts the value of the selected options into a data object with both + the id and text matching the selected value. +

+ +{% highlight js linenos %} +{ + initSelection : function (element, callback) { + var data = []; + $(element.val()).each(function () { + data.push({id: this, text: this}); + }); + callback(data); + } +} +{% endhighlight %} + +

+ When using the new current method of the custom data adapter, + this method is called any time Select2 needs a list of + the currently selected options. This is different from the old + initSelection in that it was only called once, so it could + suffer from being relatively slow to process the data (such as from a + remote data source). +

+ +{% highlight js linenos %} +$.fn.select2.amd.require([ + 'select2/data/array', + 'select2/utils' +], function (ArrayData, Utils) { + function CustomData ($element, options) { + CustomData.__super__.constructor.call(this, $element, options); + } + + Utils.Extend(CustomData, ArrayData); + + CustomData.prototype.current = function (callback) { + var data = []; + var currentVal = this.$element.val(); + + if (!this.$element.prop('multiple')) { + currentVal = [currentVal]; + } + + for (var v = 0; v < currentVal.length; v++) { + data.push({ + id: currentVal[v], + text: currentVal[v] + }); + } + + callback(data); + }; + + $("#select").select2({ + dataAdapter: CustomData + }); +} +{% endhighlight %} + +

+ The new current method of the data adapter works in a similar + way to the old initSelection method, with three notable + differences. The first, and most important, is that it is called + whenever the current selections are needed to ensure that Select2 + is always displaying the most accurate and up to date data. No matter + what type of element Select2 is attached to, whether it supports a + single or multiple selections, the data passed to the callback + must be an array, even if it contains one selection. + The last is that there is only one parameter, the callback to be + executed with the latest data, and the current element that Select2 is + attached to is available on the class itself as + this.$element. +

+ +

+ If you only need to load in the initial options once, and otherwise will + be letting Select2 handle the state of the selections, you don't need to + use a custom data adapter. You can just create the + <option> tags on your own, and Select2 will pick up + the changes. +

+ +{% highlight js linenos %} +var $element = $('select').select2(); // the select element you are working with + +var $request = $.ajax({ + url: '/my/remote/source' // wherever your data is actually coming from +}); + +$request.then(function (data) { + // This assumes that the data comes back as an array of data objects + // The idea is that you are using the same callback as the old `initSelection` + + for (var d = 0; d < data.length; d++) { + var item = data[d]; + + // Create the DOM option that is pre-selected by default + var option = new Option(item.text, item.id, true, true); + + // Append it to the select + $element.append(option); + } + + // Update the selected options that are displayed + $element.trigger('change'); +}); +{% endhighlight %} + +

+ Custom data adapters instead of query +

+ +

+ In the past, any time + you wanted to hook Select2 up to a different data source you would be + required to implement custom query and + initSelection methods. This allowed Select2 to determine the + initial selection and the list of results to display, and it would handle + everything else internally, which was fine more most people. +

+ +

+ The custom query and initSelection methods have + been replaced by + custom data adapters that handle + how Select2 stores and retrieves the data that will be displayed to the + user. An example of the old query option is provided below, + which is + the same as the old example, + and it generates results that contain the search term repeated a certain + number of times. +

+ +{% highlight js linenos %} +{ + query: function (query) { + var data = {results: []}, i, j, s; + for (i = 1; i < 5; i++) { + s = ""; + for (j = 0; j < i; j++) {s = s + query.term;} + data.results.push({id: query.term + i, text: s}); + } + query.callback(data); + } +} +{% endhighlight %} + +

+ This has been replaced by custom data adapters which define a similarly + named query method. The comparable data adapter is provided + below as an example. +

+ +{% highlight js linenos %} +$.fn.select2.amd.require([ + 'select2/data/array', + 'select2/utils' +], function (ArrayData, Utils) { + function CustomData ($element, options) { + CustomData.__super__.constructor.call(this, $element, options); + } + + Utils.Extend(CustomData, ArrayData); + + CustomData.prototype.query = function (params, callback) { + var data = { + results: [] + }; + + for (var i = 1; i < 5; i++) { + var s = ""; + + for (var j = 0; j < i; j++) { + s = s + params.term; + } + + data.results.push({ + id: params.term + i, + text: s + }); + } + + callback(data); + }; + + $("#select").select2({ + dataAdapter: CustomData + }); +} +{% endhighlight %} + +

+ The new query method of the data adapter is very similar to + the old query option that was passed into Select2 when + initializing it. The old query argument is mostly the same as + the new params that are passed in to query on, and the + callback that should be used to return the results is now passed in as the + second parameter. +

+ +

Renamed templating options

+ +

+ Select2 previously provided multiple options for formatting the results + list and selected options, commonly referred to as "formatters", using the + formatSelection and formatResult options. As the + "formatters" were also used for things such as localization, + which has also changed, they have been + renamed to templateSelection and templateResult + and their signatures have changed as well. +

+ +

+ You should refer to the updated + documentation on templates when + migrating from previous versions of Select2. +

+ +

+ The id and text properties are strictly enforced +

+ +

+ When working with array and AJAX data in the past, Select2 allowed a + custom id function or attribute to be set in various places, + ranging from the initialization of Select2 to when the remote data was + being returned. This allowed Select2 to better integrate with existing + data sources that did not necessarily use the id attribute to + indicate the unique identifier for an object. +

+ +

+ Select2 no longer supports a custom id or text + to be used, but provides integration points for converting incorrect data + to the expected format. +

+ +

+ When working with array data +

+ +

+ Select2 previously supported defining array data as an object that matched + the signature of an AJAX response. A text property could be + specified that would map the given property to the text + property on the individual objects. You can now do this when initializing + Select2 by using the following jQuery code to map the old + text and id properties to the new ones. +

+ +{% highlight js linenos %} +var data = $.map([ + { + pk: 1, + word: 'one' + }, + { + pk: 2, + word: 'two' + } +], function (obj) { + obj.id = obj.id || obj.pk; + obj.text = obj.text || obj.word; + + return obj; +}); +{% endhighlight %} + +

+ This will result in an array of data objects that have the id + properties that match the existing pk properties and + text properties that match the existing word + properties. +

+ +

+ When working with remote data +

+ +

+ The same code that was given above can be used in the + processResults method of an AJAX call to map properties there + as well. +

+ +

Renamed translation options

+ +

+ In previous versions of Select2, the default messages provided to users + could be localized to fit the language of the website that it was being + used on. Select2 only comes with the English language by default, but + provides + community-contributed translations for + many common languages. Many of the formatters have been moved to the + language option and the signatures of the formatters have + been changed to handle future additions. +

+ +

+ Declaring options using data-* attributes +

+ +

+ In the past, Select2 has only supported declaring a subset of options + using data-* attributes. Select2 now supports declaring all + options using the attributes, using + the format specified in the documentation. +

+ +

+ You could previously declare the URL that was used for AJAX requests using + the data-ajax-url attribute. While Select2 still allows for + this, the new attribute that should be used is the + data-ajax--url attribute. Support for the old attribute will + be removed in Select2 4.1. +

+ +

+ Although it was not documented, a list of possible tags could also be + provided using the data-select2-tags attribute and passing in + a JSON-formatted array of objects for tags. As the method for specifying + tags has changed in 4.0, you should now provide the array of objects using + the data-data attribute, which maps to + the array data option. You should also + enable tags by setting data-tags="true" on the object, to + maintain the ability for users to create their own options as well. +

+ +

+ If you previously declared the list of tags as… +

+ +{% highlight html linenos %} + +{% endhighlight %} + +

+ …then you should now declare it as… +

+ +{% highlight html linenos %} + +{% endhighlight %} + +

Deprecated and removed methods

+ +

+ As Select2 now uses a <select> element for all data + sources, a few methods that were available by calling + .select2() are no longer required. +

+ +

.select2("val")

+ +

+ The "val" method has been deprecated and will be removed in + Select2 4.1. The deprecated method no longer includes the + triggerChange parameter. +

+ +

+ You should directly call .val on the underlying + <select> element instead. If you needed the second + parameter (triggerChange), you should also call + .trigger("change") on the element. +

+ +{% highlight js linenos %} +$("select").val("1").trigger("change"); // instead of $("select").select2("val", "1"); +{% endhighlight %} + +

.select2("enable")

+ +

+ Select2 will respect the disabled property of the underlying + select element. In order to enable or disable Select2, you should call + .prop('disabled', true/false) on the + <select> element. Support for the old methods will be + completely removed in Select2 4.1. +

+ +{% highlight js linenos %} +$("select").prop("disabled", true); // instead of $("select").enable(false); +{% endhighlight %} + +
+