Issue
I am developing a .net core mvc webapp, and I need to have select elements that behave just like anagular dropdowns. I did research and found the datalist tag, which is basically exactly what I need, but I am concerned with a few things.
First, datalist is an input tag, not a select tag. This would allow the user to input anything they wanted, even if it is not in the options list.
Second, if the user does select an option from datalist, the text value is stored in the input. I have a country/state select that needs to store a country code instead, and it seems like I can load that code into an attribute in the options, but the text is still stored.
Third, I'm trying to keep things as minimal as possible in my typescript. I really don't want to add too much new code just to watch out for all these quirks. We can't add jquery-ui or any other externa libraries, either.
Fourth, we have functionality in our app that allows the user to load existing values into the model. Since these values for country select would be a country code, the datalist doesn't know what to do with it because datalist only works with the country name and not the code.
We already had these select elements in place. Someone suggested looking into styling normal select element to look and behave like datalist. I have heard this is not possible in css, but is that true? If so, what alternatives exist for datalist, then?
EDIT: Weird stuff going on, but wikid's answer should be the accepted solution (can't select it for some reason)
Solution
I've found this solution, by Siddhant Jaiswal who is a legend because they have put some big effort into their communication. What a legend! https://dev.to/siddev/customise-datalist-45p0
And just in case his blog goes down one day.. here is a very naughty copy and paste, which I am reproducing under fair use for educational purposes, and giving heaps props to the original author: Siddhant Jaiswal from Kolkata | Banaglore.
Here on CODEPEN: eg1. https://codepen.io/sidd_dev/pen/ExZYZmo eg2. https://codepen.io/sidd_dev/pen/qBRWNQQ
and text..
TUTORIAL STARTS HERE
- we create and input tag and add list attribute to it. This list attribute will take in the id of our datalist element Next up we will create our datalist element with ID as browsers and inside the datalist element will have some option elements as well and voila your basic datalist is complete.
<datalist id="browsers">
<option value="Internet Explorer">Internet Explorer</option>
<option value="Chrome">Chrome</option>
<option value="Safari">Safari</option>
<option value="Microsoft Edge">Microsoft Edge</option>
<option value="Firefox">Firefox</option>
</datalist>
- disable the OOB datalist and to do that we simply need to pass empty string to our input list attribute.
<input autocomplete="off" list="" id="input"
name="browsers" placeholder="Select your fav browser">
- add some basic CSS to our datalist and options elements
datalist {
position: absolute;
background-color: white;
border: 1px solid blue;
border-radius: 0 0 5px 5px;
border-top: none;
font-family: sans-serif;
width: 350px;
padding: 5px;
}
option {
background-color: white;
padding: 4px;
color: blue;
margin-bottom: 1px;
font-size: 18px;
cursor: pointer;
}
Please not CSS for input element can be found in codepen above. Now we want the our datalist to be displayed when the focus on our input element and for this we will some Javascript.
input.onfocus = function () {
browsers.style.display = 'block';
input.style.borderRadius = "5px 5px 0 0";
};
for (let option of browsers.options) {
option.onclick = function () {
input.value = option.value;
browsers.style.display = 'none';
input.style.borderRadius = "5px";
}
};
We will also add hover styling so that the option is highlighted when we hover over any option
option:hover, .active{
background-color: lightblue;
}
We will use active class later. Now this will make your datalist work and users will be able to select any option via mouse but won't work with keyboard input.
- filter to the options based on input values. To do that we will create an oninput trigger and get the values then will match the values with our options and display only the options that match with input values.
input.oninput = function() {
var text = input.value.toUpperCase();
for (let option of browsers.options) {
if(option.value.toUpperCase().indexOf(text) > -1){
option.style.display = "block";
}else{
option.style.display = "none";
}
};
}
Here we simply take the input value convert them to uppercase and then see if that input is present at any index for each option values. if yes then display it else hide it.
- add the functionality for tracking the options via keyboard up and down arrow keys and select any option using enter. For this we will need to track the currectFocus for our option element so we will define a variable as currentFocus = -1, then check for keyboard input keycode to be up or down arrow keys and toggle the active class defined earlier.
var currentFocus = -1;
input.onkeydown = function(e) {
if(e.keyCode == 40){
currentFocus++
addActive(browsers.options);
}
else if(e.keyCode == 38){
currentFocus--
addActive(browsers.options);
}
else if(e.keyCode == 13){
e.preventDefault();
if (currentFocus > -1) {
if (browsers.options)
browsers.options[currentFocus].click();
}
}
}
function addActive(x) {
if (!x) return false;
removeActive(x);
if (currentFocus >= x.length) currentFocus = 0;
if (currentFocus < 0)
currentFocus = (x.length - 1);
x[currentFocus].classList.add("active");
}
function removeActive(x) {
for (var i = 0; i < x.length; i++) {
x[i].classList.remove("active");
}
}
and we have recreated the default datalist.
Answered By - wikid
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.