bootstrap-select
bootstrap-select copied to clipboard
Ability to select/deselect all optgroup items
I need to clickable optgroup option, when we click on the optgroup label to select / deselect what are all items having inside the groups are selected /deselected. This is very urgent please...
Hello Silvio,
Is there any chance that we get some help about this? Thanks.
Any support regarding this?
Looking forward to this functionality too.
Also, duplicate of #680, in which @t0xicCode tagged this functionality for the 1.7.0 milestone.
It would be nice and seems logical.
Looking forward for that.
For anybody who truly needs this right now, replace these lines here: https://github.com/silviomoreto/bootstrap-select/blob/master/js/bootstrap-select.js#L957-L965 with
this.$menu.on('click', 'li.divider, li.dropdown-header', function (e) {
e.preventDefault();
e.stopPropagation();
if (that.multiple && $(e.currentTarget).hasClass('dropdown-header')) {
var $options = that.$element.find('option'),
$optgroup = $(e.currentTarget),
optgroupID = $optgroup.data('optgroup'),
$optgroupLis = that.$lis.filter('[data-optgroup="' + optgroupID + '"]').not('.divider, .dropdown-header, .disabled, .hidden'),
selectAll = $optgroupLis.filter('.selected').length !== $optgroupLis.length;
if (!$options.eq($optgroupLis.data('originalIndex')).parent().data('maxOptions')) {
$optgroupLis.each(function(index) {
var $this = $(this);
$options.eq($this.data('originalIndex')).prop('selected', selectAll);
});
$optgroupLis.toggleClass('selected', selectAll);
that.render(false);
}
}
if (that.options.liveSearch) {
that.$searchbox.focus();
} else {
that.$button.focus();
}
});
I was going to implement this, but thought it would be best to first discuss how best to handle optgroups with maxOptions set. With this code, if an optgroup has maxOptions set, clicking the optgroup label doesn't do anything. Anybody have any ideas for a different way to handle this?
I agree with your suggestion. I don't see a better way to deal with the limited number of options. Maybe it's also a good idea to add some kind of notification in that case, so that users are also aware of it?
@caseyjhol :+1: thanks a lot :-)
Hi @caseyjhol, Are there a new solution for this? I know that now we have a new version Selectpicker.VERSION = '1.7.2'; Or someone else have another solution for this? thanks a lot:)
+1 for this
@caseyjhol, can you reconfirm the lines to be replaced for the actual version? I really would like to try this feature. And for the conflict, maybe the best option should be document it. There some of this kinda of stuff on Bootstrap and they just document it. Well this being said there is not a practical solution that don't create a conflict with another feature. Thanks.
+1
In regard to how to deal with maxOptions... just check the first maxOptions items.
@caseyjhol Hey, I've got the majority of this working on a fork at the moment. The only thing I have left to do is fix some CSS a bit so it looks clickable and add to the documentation.
Brief explanation of maxOptions problem
When I first read this, I didn't fully understand the issue of maxOptions until I started building it and ran into the same issue. So this is a brief explanation to catch up anyone else who needs it:
- If you use the
data-max-options="3"attribute to the<optgroup>it will only let you select three options, even if you have more. - If you add the ability to select all options under an
<optgroup>that has a max options that is less than the total options, which options do you choose to select?
The current functionality I have working is the follows:
Selects the first few if maxOptions is set
I incorporated the idea from @weatherbell to select the first maxOptions. I like this idea a lot because if the user is confused, the first thing the user will try to do is select the next few which will then force the warning: Group limit reached ({n} item max). So any confusion is self-fixing.
It's a data attribute
In order for the programmer to add the "select header" functionality, they must add the data-select-all-headers="true" attribute to their <select> like so:
<select id="selectHeader" class="selectpicker form-control" multiple data-select-all-headers="true" title="Selecting a header will select all it can.">
<!-- Options with groups -->
</select>
Requiring this to be opt-in solves a number of issues. It solves the point made by @Khrysller that we should document it. By requiring it to be opt-in, we force the programmer to read the documentation explaining the oddities caused by maxOptions. It also puts both the burden and freedom of usability on the programmer.
I'm going to continue working on the documentation and css unless anyone has any disagreements with this plan.
Note that the existing Select All ability currently ignores the maxOptions. In practice, it doesn't really make sense to have a "select all" while at the same time having a limit on the number of options you can select. I highly doubt anyone would be trying to use both these features at once, so going to extra lengths to make them somehow work together may not be particularly helpful.
Personally I would say the sensible thing to do is either ignore the maxOptions (as it currently does for the main select all) or force the select all option off if maxOptions is defined.
I had problems with the above code and the function "change". Solved by adding "onselect" directly on the tag <select>:
<select class="form-control selectpicker" name="mynames[]"
multiple="multiple" onchange="changeSelectPicker(this)">
<option value="1">Count 1</option>
<option value="2">Count 2</option>
<option value="3">Count 3</option>
<option value="4">Count 4</option>
</select>
// PROBLEM
$('.selectpicker').on("changed.bs.select", function (e, clickedIndex) {
console.log(this); // NO RETURN
});
// PROBLEM
$('.selectpicker').on("change", function (this) {
console.log(this); // NO RETURN
});
// SOLVED
function changeSelectPicker(that) {
var valuesArr = $(that).val();
console.log(valuesArr); // return selected values ["1", "3", "4"]
}
@Flaque Have you done anything else with this? Can you post what you have?
Sorry, @KrunchMuffin. I haven't done anything more than the original PR. I guess I missed this. I might be able to look into it, but no promises.
Ah, sorry, didn't see the PR. What I am really after is the ability to use Select All while minding the maxOptions. I may be able to do something with your code.
Any plans on integrating these changes? Is there a workaround available to gain this functionality or at least trap the click event on the optgroup?
For actual version this works for me, simply add this:
$("li.dropdown-header").click(function(e){
e.preventDefault();
e.stopPropagation();
if (that.multiple && $(e.currentTarget).hasClass('dropdown-header')) {
var $options = that.$element.find('option'),
$optgroup = $(e.currentTarget),
optgroupID = $optgroup.data('optgroup'),
$optgroupLis = that.$lis.filter('[data-optgroup="' + optgroupID + '"]').not('.divider, .dropdown-header, .disabled, .hidden'),
selectAll = $optgroupLis.filter('.selected').length !== $optgroupLis.length;
if (!$options.eq($optgroupLis.data('originalIndex')).parent().data('maxOptions')) {
$optgroupLis.each(function(index) {
var $this = $(this);
$options.eq($this.data('originalIndex')).prop('selected', selectAll);
});
$optgroupLis.toggleClass('selected', selectAll);
that.render(false);
}
}
if (that.options.liveSearch) {
that.$searchbox.focus();
} else {
that.$button.focus();
}
});
in line 1358 (https://github.com/silviomoreto/bootstrap-select/blob/master/js/bootstrap-select.js#L1358)
@caseyjhol Are there any solutions to achieve the same in the version compatible with bootstrap-4.0 i.e. bootstrap-select-v1.13.0-beta version?
I am also interested in this feature for bootstrap-4.0 i.e. bootstrap-select-v1.13.0-beta version.
jerearaujo03 thanks for sharing - your code works fine if you have ONE selectlist on your page. If you have more, this works for me:
this.$menuInner.find( "li.dropdown-header" ).each(function(index) {
$(this).on('click',function(e) {
e.preventDefault();
e.stopPropagation();
if (that.multiple && $(e.currentTarget).hasClass('dropdown-header')) {
var $options = that.$element.find('option'),
$optgroup = $(e.currentTarget),
optgroupID = $optgroup.data('optgroup'),
$optgroupLis = that.$lis.filter('[data-optgroup="' + optgroupID + '"]').not('.divider, .dropdown-header, .disabled, .hidden'),
selectAll = $optgroupLis.filter('.selected').length !== $optgroupLis.length;
if (!$options.eq($optgroupLis.data('originalIndex')).parent().data('maxOptions')) {
$optgroupLis.each(function(index) {
var $this = $(this);
$options.eq($this.data('originalIndex')).prop('selected', selectAll);
});
$optgroupLis.toggleClass('selected', selectAll);
that.render(false);
}
}
if (that.options.liveSearch) {
that.$searchbox.focus();
} else {
that.$button.focus();
}
});
});
Great!
It's not work for me ...
The previous posted solution does not work on the current version which has a different code base. Can we have a updated solution or a built in feature for toggling select all items under an option group please? Will pay/donate for this!
Someone provided a solution that worked for me: https://stackoverflow.com/questions/41821115/select-deselect-optgroup-based-on-option-select-in-select-picker-boostrap
I did this, just add this bottom of the page:
$(".dropdown-header").each(function (index, header) {
var header = $(header);
header.click(function () {
var dataoptgroup = $(this).attr("data-optgroup");
var group_lis = $('li[data-optgroup=' + dataoptgroup + ']').filter('li[data-original-index]');
group_lis.each(function (index, option) {
$(option).find("a").click()
});
});
});
I did this, just add this bottom of the page:
$(".dropdown-header").each(function (index, header) {
var header = $(header); header.click(function () { var dataoptgroup = $(this).attr("data-optgroup"); var group_lis = $('li[data-optgroup=' + dataoptgroup + ']').filter('li[data-original-index]'); group_lis.each(function (index, option) { $(option).find("a").click() }); }); });
v1.13.12 works for me:
add this in this.$menuInner.on('click', '.divider, .dropdown-header', function (e) line 2521:
if(that.multiple){ var group_id= $(this).attr("class").split(' ')[1]; $("li."+group_id+' a').trigger('click')};
Hi, i really need that too. There is solutions but no PR ?