Skip to content

Instantly share code, notes, and snippets.

@RyadPasha
Created October 1, 2024 21:35
Show Gist options
  • Select an option

  • Save RyadPasha/dbf29cf3b66abef11be82175355990c6 to your computer and use it in GitHub Desktop.

Select an option

Save RyadPasha/dbf29cf3b66abef11be82175355990c6 to your computer and use it in GitHub Desktop.
Populates a `selectpicker` with grouped options, supporting dynamic field keys and optional limits on group and total selections.
function populateSelectWithGroups(data, valueKey = 'value', contentKey = 'content', checkedKey = 'checked', maxSelectionsPerGroup = null, maxSelections = null) {
const $selectElement = $('#prerequisite_id');
// Clear existing options
$selectElement.empty();
// Loop through the object to create and append option groups
$.each(data, function(groupLabel, options) {
// Create the optgroup element using jQuery
const $optGroup = $('<optgroup>').attr('label', groupLabel);
// Loop through each option in the group
$.each(options, function(_, option) {
// Create the option element
const $option = $('<option>')
.val(option[valueKey] || '') // Set the value dynamically or use an empty string if not present
.text(option[contentKey] || ''); // Set the content dynamically or use an empty string if not present
// Check if the 'checkedKey' exists and apply it
if (checkedKey && option.hasOwnProperty(checkedKey) && option[checkedKey]) {
$option.prop('selected', true); // Set as selected if 'checked' is true
}
// Append the option to the optgroup
$optGroup.append($option);
});
// Append the optgroup to the select element
$optGroup.appendTo($selectElement);
});
// Refresh the selectpicker to apply changes and enable live search
$selectElement.selectpicker('refresh');
// Add event listener to limit selections
$selectElement.on('changed.bs.select', function (e, clickedIndex, isSelected, previousValue) {
const totalSelected = $selectElement.find('option:selected').length;
// Iterate through each optgroup to handle group limits
$selectElement.find('optgroup').each(function() {
const groupLabel = $(this).attr('label');
const selectedInGroup = $(this).find('option:selected').length;
// Handle maxSelectionsPerGroup
if (maxSelectionsPerGroup && selectedInGroup >= maxSelectionsPerGroup) {
// Disable unselected options within the same group
$(this).find('option:not(:selected)').prop('disabled', true);
} else {
// Enable options if the limit is not reached
$(this).find('option:not(:selected)').prop('disabled', false);
}
});
// Handle maxSelections (general total limit)
if (maxSelections && totalSelected >= maxSelections) {
// Disable all unselected options if total limit is reached
$selectElement.find('option:not(:selected)').prop('disabled', true);
} else if (!maxSelections || totalSelected < maxSelections) {
// Ensure that group-specific restrictions are applied only if maxSelections is not exceeded
$selectElement.find('optgroup').each(function() {
const selectedInGroup = $(this).find('option:selected').length;
if (!maxSelectionsPerGroup || selectedInGroup < maxSelectionsPerGroup) {
$(this).find('option:not(:selected)').prop('disabled', false);
}
});
}
// Refresh selectpicker to apply disabled/enabled state changes
$selectElement.selectpicker('refresh');
});
}
// Example object with groups
const data = {
"Group 1": [
{ id: 1, title: "Option 1", isChecked: true },
{ id: 2, title: "Option 2" },
{ id: 3, title: "Option 3" }
],
"Group 2": [
{ id: 4, title: "Option 4" },
{ id: 5, title: "Option 5", isChecked: true },
{ id: 6, title: "Option 6" }
]
};
// Call the function with both limits: maxSelectionsPerGroup = 2, maxSelections = 4
populateSelectWithGroups(data, 'id', 'title', 'isChecked', 2, 4);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment