I\'m having trouble using the Select2 with various groups, only the latter appears.
This solution was tested using select2 version 4.0.1, and you can do this way:
Pass one array that contains one attribute more (the level of every node in the hierarchy). The array's structure is simple
Create a function to format results,that is, how looks like every item according its level inside of hierarchy
When initialize select, set the function created to attribute templateResult
You can see in the follow code:
$(document).on("ready", function() {
var data = [{
id: "2",
text: "2 - Gastos",
level: 1
}, {
id: "2.1",
text: "2.1 - DESPESA OPERACIONAL FIXA",
level: 2
}, {
id: "2.1.1",
text: "2.1.1 - PESSOAL",
level: 3
}, {
id: "2.1.1",
text: "2.1.1 - PESSOAL",
level: 4
}, {
id: "2.1.1.1",
text: "2.1.1.1 - GERENCIA/ADMINSTRATIVO",
level: 4
}, {
id: "2.1.1.1.1",
text: "2.1.1.1.1 - SALÁRIOS",
level: 5
}, {
id: "2.1.1.1.2",
text: "2.1.1.1.2 - DIVIDENDOS / COMISSÕES /BONUS",
level: 5
}, {
id: "2.1.1.1.3",
text: "2.1.1.1.3 - INSS",
level: 5
}, {
id: "2.1.1.1.4",
text: "2.1.1.1.4 - FGTS",
level: 5
}];
function formatResult(node) {
var $result = $('<span style="padding-left:' + (20 * node.level) + 'px;">' + node.text + '</span>');
return $result;
};
$("#mySelect").select2({
placeholder: 'Select an option',
width: "600px",
data: data,
formatSelection: function(item) {
return item.text
},
formatResult: function(item) {
return item.text
},
templateResult: formatResult,
});
});
<!DOCTYPE html>
<html>
<head runat="server">
<title></title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.2-rc.1/css/select2.min.css" rel="stylesheet" />
</head>
<body>
<select id="mySelect">
</select>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.1/js/select2.full.min.js"></script>
</body>
</html>
I used like this. Working Fine.
$(document).on("ready", function() {
function formatResult(node) {
var level = 0;
if(node.element !== undefined){
level = (node.element.className);
if(level.trim() !== ''){
level = (parseInt(level.match(/\d+/)[0]));
}
}
var $result = $('<span style="padding-left:' + (20 * level) + 'px;">' + node.text + '</span>');
return $result;
};
$("#select2").select2({
placeholder: 'Select an option',
width: "300px",
templateResult: formatResult,
});
});
<!DOCTYPE html>
<html>
<head runat="server">
<title></title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css" rel="stylesheet" />
</head>
<body>
<select id="select2" data-placeholder="Select an option" tabindex="-1" aria-hidden="true">
<option></option>
<optgroup label="Base">
<option class="level_0" value="0">Base Parent</option>
</optgroup>
<option class="level_1" value="11">A</option>
<option class="level_2" value="12">Ant</option>
<option class="level_3" value="15">Fire Ant</option>
<option class="level_2" value="14">Apple</option>
<option class="level_1" value="13">B</option>
</select>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.min.js"></script>
</body>
</html>
Take a look at this GitHub issue. What matters is
HTML itself forbids nesting
<optgroup>
s, so your markup is invalid before it even reaches Select2. However, you can arbitrarily nest choices via children when you use JS objects to represent the choices.
This means that you can use children
to get multiple nested options. The following solution and jsfiddle are based on fperie's solution.
<input name="txtConta" id="txtConta" data-placeholder="Selecione a conta" />
<script>
var data = [
{id: "2", name: "2 - Gastos", children: [
{id: "2.1", name: "2.1 - DESPESA OPERACIONAL FIXA", children: [
{id: "2.1.1", name: "2.1.1 - PESSOAL", children: [
{id: "2.1.1", name: "2.1.1 - PESSOAL"},
{id: "2.1.1.1", name: "2.1.1.1 - GERENCIA/ADMINSTRATIVO", children: [
{id: "2.1.1.1.1", name: "2.1.1.1.1 - SALÁRIOS"},
{id: "2.1.1.1.2", name: "2.1.1.1.2 - DIVIDENDOS / COMISSÕES /BONUS"},
{id: "2.1.1.1.3", name: "2.1.1.1.3 - INSS"},
{id: "2.1.1.1.4", name: "2.1.1.1.4 - FGTS"}
]}
]}
]}
]}
];
$('#txtConta').select2({
allowClear: true,
width: 'resolve',
dropdownAutoWidth: true,
width: '400px',
data: {results: data, text: "name"},
formatSelection: function(item) {
return item.name
},
formatResult: function(item) {
return item.name
}
});
</script>
With this solution the leafs are still selectable. If you don't want to select the leafs you should remove the id
attribute from the leafs.
See this JSfiddle that demonstrates both configurations. Take note that I've only used a portion of the data you provided.
I tried adding this as a comment to Saravanan's post above, but the length of the comment was too long, so consider this as an expansion to his post, and credit goes to him for giving me the idea.
This is a bit of a necro post from me, but just wanted to expand on how I implemented the above solution with the newer jquery format of $document.ready instead of $document.on. Slightly modified as well, since I have mine nested in a pageLoad, and thus the function is outside the pageLoad, and I used an attribute rather than a class. Important part though, is that I had to put both templateResult and templateSelection for it to work, as without the latter, nothing happened:
function pageLoad() {
$(document).ready(function () {
$(".multiple-group").select2({
allowClear: true,
closeOnSelect: false,
templateResult: formatResult,
templateSelection: formatResult
});
});
}
function formatResult(node) {
var level = 0;
if (node.element !== undefined) {
level = node.element.getAttribute("hierarchy-level");
if (level.trim() !== '') {
level = parseInt(level) - 1;
}
}
var $result = $('<span style="padding-left:' + (15 * level) + 'px;">' + node.text + '</span>');
return $result;
}