Monday, 8 June 2015

Migrating to Select2 version 4.0.0. including a simple AMD Loader Fix in XPages

Select2 gives you a customizable select box with support for searching, tagging, remote data sets, infinite scrolling, and many other highly used options. In this blog post I will show how to 'migrate' in a simple manner to the new version including the most simple AMD Loader fix that always works without any problem. In the following example is transitioned from version 3.5.1 to 4.0.0 (for using Select2 version 3.5.1 see the blog post Using Select2 in XPages Part I.
In order to use Select2, the JavaScript and CSS file(s) need to be included on the XPage / Custom Control. The latest version can be downloaded from GitHub: Select2 version 4.0.0.

Adding the JS and CSS files
The JavaScript and CSS files must be added to the WebContent Folder in the Package Explorer.
In this example a Folder select2V4 has been added in the WebContent Folder.


Next the JavaScript and CSS files, select2.js and select2.css, must be included on the XPage or Custom Control. In this example I add the files to a Custom Control.

<script type="text/javascript" src="select2v4/js/select2.js"></script>
<link rel="stylesheet" href="select2v4/css/select2.css" />

Adding the x$ jQuery selector for XPages
Furthermore I use the the great XSnippet by Mark Roden (again), x$ jQuery selector for XPages, to initialize the plugin and include it on the Custom Control / XPage. The XSnippet can be added to the Script Libraries.


<xp:this.resources>
<xp:script src="/JQueryXSnippet.js" clientSide="true"></xp:script>
</xp:this.resources>

The script itself can be made up as follows. The name of the id in the script must correspond with the id of the Combo Box / List Box.

<xp:scriptBlock id="scriptBlock2">
<xp:this.value><![CDATA[
$(document).ready(
function() {
x$( "#{id:comboBox1}" ).select2({
placeholder: "Select a category",
allowClear: true
});
}
);
]]></xp:this.value>
</xp:scriptBlock>

Remark: When a placeholder is used for a non-multi-value select box such as a Combo Box, an empty tag is required as a first option. One possibility is to generate computed items, including an empty tag, as values for the Combo Box.

var arr = new Array("");  
var res = @DbLookup("", "byKeyWord", "Category", 2);
var list = arr.concat(res);
return list;

Optionally, a clear button (visible once a selection is made) is available to reset the select box back to the placeholder value (allowClear: true).

AMD Loader Fix
Finally, the JavaScript file select2.js needs to be adjusted. Reason: newer jQuery plugins try to use its AMD loader, but that doesn't play well with the Dojo implementation in XPages. The source code of the library can be adjusted in a very simple way with just a slight modification. This solution is put forward by Mark Roden in one of his recent blog posts. Select2 v4 needs AMD fixing in Domino R9 XPages.

1. Go to the WebContent Folder and select the JavaScript file select2.js
2. Select Open With - Client/Server JS Editor


3. Removed in the second line define.amd and replace it with false 


4. Save the JavaScript file select2.js

Responsive design - Percent width
Select2's width can be set to a percentage of its parent to support responsive design.
The best way to ensure that Select2 is using a percent based width is to inline the style declaration into the tag.
In the All Properties of the Combo Box set the Property style to the desired percentage.
I always use: style="width: 100% !important;"

Basic Setup Combo Box in XPages
<div class="col-md-7">
<div class="panel panel-default">
<div class="panel-body">
Select2 - Combo Box
<xp:comboBox id="comboBox1" value="#{document1.Categories}" style="width: 100% !important;">
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:var arr = new Array("");  
var res = @DbLookup("", "byKeyWord", "Category", 2);
var list = arr.concat(res);
return list;}]]></xp:this.value>
</xp:selectItems>
</xp:comboBox>
</div>
<div class="panel-footer">Combo Box - Single Value</div>
</div>
</div>

The result is a  good looking Bootstrap style select box.


Example with List Box (multi value)
Select2 also supports multi-value select boxes. The select below is declared with the multiple data-attribute.

<div class="col-md-7">
<div class="panel panel-default">
<div class="panel-body">
Select2 - List Box
<xp:listBox id="listBox1" value="#{document1.Categories}" style="width: 100% !important;">
<xp:this.attrs>
<xp:attr name="multiple" value="multiple"></xp:attr>
</xp:this.attrs>
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript: @DbLookup("", "byKeyWord", "Software", 2);}]]></xp:this.value>
</xp:selectItems>
</xp:listBox>
</div>
<div class="panel-footer">List Box - Multiple Values</div>
</div>
</div>

The result is a  good looking Bootstrap style multi select box.


Code Custom Control
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:this.data>
<xp:dominoDocument var="document1" formName="Contact"></xp:dominoDocument>
</xp:this.data>
<xp:this.resources>
<xp:script src="/JQueryXSnippet.js" clientSide="true"></xp:script>
</xp:this.resources>
<script type="text/javascript" src="select2v4/js/select2.js"></script>
<link rel="stylesheet" href="select2v4/css/select2.css" />
<xp:scriptBlock id="scriptBlock2">
<xp:this.value><![CDATA[
$(document).ready(
function() {
x$( "#{id:comboBox1}" ).select2({
placeholder: "Select a category",
allowClear: true
});
});
]]></xp:this.value>
</xp:scriptBlock>
<xp:scriptBlock id="scriptBlock1">
<xp:this.value><![CDATA[
$(document).ready(
function() {
x$( "#{id:listBox1}" ).select2({
placeholder: "Select a software category",
allowClear: true
});
});
]]></xp:this.value>
</xp:scriptBlock>
<xp:panel>
<div class="page-header">
<h1>Select2 - Version 4.0.0 <xp:span style="color:rgb(255,255,255)">.</xp:span>
<small>Combo Box / List Box</small>
</h1>
</div>
<div class="col-md-7">
<div class="panel panel-default">
<div class="panel-body">
Select2 - Combo Box
<xp:comboBox id="comboBox1" value="#{document1.Categories}" style="width: 100% !important;">
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:var arr = new Array("");  
var res = @DbLookup("", "byKeyWord", "Category", 2);
var list = arr.concat(res);
return list;}]]></xp:this.value>
</xp:selectItems>
</xp:comboBox>
</div>
<div class="panel-footer">Combo Box - Single Value</div>
</div>
</div>
<div class="col-md-7">
<div class="panel panel-default">
<div class="panel-body">
Select2 - List Box
<xp:listBox id="listBox1" value="#{document1.Categories}" style="width: 100% !important;">
<xp:this.attrs>
<xp:attr name="multiple" value="multiple"></xp:attr>
</xp:this.attrs>
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript: @DbLookup("", "byKeyWord", "Software", 2);}]]></xp:this.value>
</xp:selectItems>
</xp:listBox>
</div>
<div class="panel-footer">List Box - Multiple Values</div>
</div>
</div>
</xp:panel>
</xp:view>

For more Core Options I refer to the documentation: Options.

Concluding Remark
In the above examples I've used the following basic view.

2 comments:

  1. What a great article! With this step-by-step recipe I managed to use select2 in my XPages project.

    ReplyDelete