Hi, coders!
Two days ago I posted a real world mini challenge that I was tasked to implement.
Specifications are simple enough:
users should be able to select as many cities as they like from a drop down as long as they're not located in more than 2 countries.
RTFM
As often is the case, reading the documentation goes a long way. This time is no exception.
If you head over to the events section of the doc you will see that you can listen to changed.bs.select
which is fired right after the underlying select value changed.
$('#mySelect').on('changed.bs.select', function (e, clickedIndex, isSelected, previousValue) {
// do something...
});
What's important here is that we also get previousValue
which, you guessed it, holds the drop down value before it was changed.
So if we can figure out when a user has selected a third country then we can just set the value back to previousValue
by doing:
$("#cities")
.selectpicker()
.on(
"changed.bs.select",
function (event, clickedIndex, isSelected, previousValue) {
const $this = $(this);
if (someCondition) { // <== gotta work on this next
$this.selectpicker('val', previousValue);
}
}
);
Counting how many countries are selected
We don't just want the number of selected cities but the number of countries they belong to.
The only info we have is the optgroup
label and we'll use just that.
const selectedCountries = $this
.find("option:selected")
.get()
.map((o) => $(o).parent().attr("label"))
We're basically looping on each selected option and grab their optgroup
's label.
The problem is that country names are not unique if more than one city is selected.
If you've been reading JavaScript related posts here on dev.to then you've probably seen the following one liner which gets unique values from someArray
:
const uniqueNames = [new Set(...someArray)];
Exactly what we want so let's use it:
const uniqueCategories = [
...new Set(
$this
.find("option:selected")
.get()
.map((o) => $(o).parent().attr("label"))
)
];
Now that we have a unique list of countries we just need to count the number of elements and if it's greater than 2 then we just set the dropdown's value to previousValue
.
if (uniqueCategories.length > 2) {
$this.selectpicker('val', previousValue);
}
Putting it all together
$(function () {
const MAX_NUMBER_COUNTRIES = 2;
$("#cities")
.selectpicker()
.on(
"changed.bs.select",
function (event, clickedIndex, isSelected, previousValue) {
const $this = $(this);
const uniqueCategories = [
...new Set(
$this
.find("option:selected")
.get()
.map((o) => $(o).parent().attr("label"))
)
];
if (uniqueCategories.length > MAX_NUMBER_COUNTRIES) {
$this.selectpicker('val', previousValue);
}
}
);
});
See it in action on CodePen.
Conclusion
Although this "challenge" was not difficult it shows how important it is to read the doc!
Back when I was a student our Java teacher challenged us to write the shortest possible program to manipulate some strings.
Some came up with a 7 lines program. Others had 4 lines.
The teacher's had ONE line. ✨
It was just a call to a native Java function which did exactly what was asked. His way of saying RTFM but in a politically correct way.
Happy coding! 💻
Top comments (0)