How to use "invalid-feedback" class with selectpicker from Bootstrap-Select? - html

I'm using Bootstrap to do some form validation on my web app. With a normal select menu, it would be really easy to have an error message pop-up when the field is invalid:
<select class="someClass" required>
<option value="">Select an option</option>
<option>foo</option>
<option>bar</option>
</select>
<div class="invalid-feedback">Please make a selection.</div>
However, I'm using Bootstrap-Select's "selectpicker" class, and the "invalid-feedback" message in the div no longer works. Is there anyway to force Bootstrap-Select to recognize the "invalid-feedback" class or am I going to have to go about this a different way?

I figured out how to do this, and more generally this is an answer for anytime you have to "manually" force an error to work with Bootstrap's native validation system. It's really hacky, but I couldn't find anything else that works.
Say you have a "selectpicker" that looks like this:
<select id="mySelect" class="selectpicker" required>
<option value="">Select an option</option>
<option>foo</option>
<option>bar</option>
</select>
<div id="error" class="invalid-feedback">Please make a selection.</div>
The error message "Please make a selection" will not show, even if the select element is invalid; it will show, however, if it also has the "d-block" class:
<div id="error" class="invalid-feedback d-block">Please make a selection.</div>
So to manually force errors, you have to use JavaScript to check for the ":invalid" CSS pseudo-class; if it has this pseudo-class, then you add the "d-block" class to your div to show the error. You can use the matches() method and classList.add():
var selector = document.getElementById("mySelect");
var errorMsg = document.getElementById("error");
if(selector.matches(":invalid"))
{
errorMsg.classList.add("d-block");
}
You do this to add the message and you can remove it by checking for ":valid" and removing "d-block" from the classList.

I had multiple versions of the bootstrap-select elements in one of my forms and was having a really hard time getting this to work. The method below won't show the checkmark or x on the input, but it will show the invalid-feedback and valid-feedback boxes properly.
Using the advice from secretagentmango's answer, you can create a function that loops through all of your inputs with the "selectpicker" class, grab their parent form-group element, and then find the children "valid-feedback" and "invalid-feedback" elements
to add or remove the d-block class and hide/show them.
function bsSelectValidation() {
if ($("#myForm").hasClass('was-validated')) {
$(".selectpicker").each(function (i, el) {
if ($(el).is(":invalid")) {
$(el).closest(".form-group").find(".valid-feedback").removeClass("d-block");
$(el).closest(".form-group").find(".invalid-feedback").addClass("d-block");
}
else {
$(el).closest(".form-group").find(".invalid-feedback").removeClass("d-block");
$(el).closest(".form-group").find(".valid-feedback").addClass("d-block");
}
});
}
}
Now you need to run this function after form submit, and you can add it directly to the sample code from the Bootstrap Docs:
(function () {
'use strict';
window.addEventListener('load', function () {
// Fetch all the forms we want to apply custom Bootstrap validation styles to
var forms = document.getElementsByClassName('needs-validation');
// Loop over them and prevent submission
var validation = Array.prototype.filter.call(forms, function (form) {
form.addEventListener('submit', function (event) {
if (form.checkValidity() === false) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated');
bsSelectValidation();
}, false);
});
}, false);
})();
The only thing different in the above code from bootstrap's sample is the call to our new function, "bsSelectValidation".
Now you need to listen for changes in the form to automatically update the d-block classes and fix the valid/invalid messages as people make changes to the form:
$('#myForm').change(bsSelectValidation);
Now your select menus should properly show the valid-feedback and invalid-feedback divs on form submit or change.

I found that if I simply remove the value="" part of the "option" element, then the validation message shows properly. That is, if I don't select anything from the dropdown, the my "invalid-feedback" message shows up. When I select something, it goes away and I can proceed further. It's worth a try if you haven't tried it.
My first "option" is simply this: <option>(select)</option> -- no 'value' clause is present.
Hope this helps.

Related

What is the HTML <dialog> tag used for and when to use it?

The way I've understood it, the tag is used to open and close content like a popup alert. What I fail to understand is what advantages the tag has compared to just using a "div" and styling it with css and adding functionality to it with js. It also seems counter intuitive to manipulate the "open" property in order to show/hide the content instead of using display:none/block; with css.
I also don't understand exactly which scenarios would be considered a dialog box. Is a form login box a dialogbox? What about a popup telling you to disable adblock? Are all popups that can be hidden considered dialog boxes?
The traditional, hacky way to create a dialog, via designing a div via CSS only seems to be intuitive for you because you are used to it. However, you need to implement every functionality related to it, such as:
opening it
closing it
Also, in the future, this will be enhanced by standard functionalities, so, while it's not urgent for already existent code, but when you write code, especially when you start a project, it makes sense to start using it. Let's see an example from [Mozilla's page][1]:
var updateButton = document.getElementById('updateDetails');
var favDialog = document.getElementById('favDialog');
var outputBox = document.querySelector('output');
var selectEl = document.querySelector('select');
var confirmBtn = document.getElementById('confirmBtn');
// "Update details" button opens the <dialog> modally
updateButton.addEventListener('click', function onOpen() {
if (typeof favDialog.showModal === "function") {
favDialog.showModal();
} else {
alert("The <dialog> API is not supported by this browser");
}
});
// "Favorite animal" input sets the value of the submit button
selectEl.addEventListener('change', function onSelect(e) {
confirmBtn.value = selectEl.value;
});
// "Confirm" button of form triggers "close" on dialog because of [method="dialog"]
favDialog.addEventListener('close', function onClose() {
outputBox.value = favDialog.returnValue + " button clicked - " + (new Date()).toString();
});
<!-- Simple pop-up dialog box containing a form -->
<dialog id="favDialog">
<form method="dialog">
<p><label>Favorite animal:
<select>
<option></option>
<option>Brine shrimp</option>
<option>Red panda</option>
<option>Spider monkey</option>
</select>
</label></p>
<menu>
<button value="cancel">Cancel</button>
<button id="confirmBtn" value="default">Confirm</button>
</menu>
</form>
</dialog>
<menu>
<button id="updateDetails">Update details</button>
</menu>
<output aria-live="polite"></output>
However, at the time of this writing (February the 3rd, 2022), this is not supported in all browsers, so it is perfectly feasible to avoid using it for now, until it will become supported everywhere.
[1]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog

HTML 5 Datalist - How to autoselect if only one option is available

User types into the input box with datalist attached, one option is displayed that they can click on to select. How can I auto select that single option?
Okay so datalist is an HTML5 element that allows for a native autocomplete feature on most modern browsers. That being said it does not provide the ability to set a default or selected option. Additionally it does not have events available so you need to do it using standard events on your elements.
Example
$(document).ready(function () {
var datalist = $('#someCountries');
var opts = datalist.find('option');
console.log(opts.val());
console.log(opts.length);
function checkOpts() {
if (opts.length === 1) {
$('#country').val(opts.val());
}
}
$('#country').on('focusin', checkOpts);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="country" list="someCountries" />
<datalist id="someCountries">
<option label="United Stated" value="USA"></option>
</datalist>
You will probably need to modify the focusin event to something more appropriate for your situation, but this should get you on your way.

Html DropDownList not generating events

In my web page I use something like this, but when a option is selected, onchange is not fired. I don't know where I have made a mistake. Actually my requirements is that I need to fetch location details based on the city selected, but it is not working here. Is there any other better way to do so?
#Html.DropDownList("cities", ViewBag.cities as SelectList, new { onselect = "getLoca();"});
<script type="text/javascript">
function getLoca() {
alert("yes");
$.post('#Url.Action("getLocations","Home")', { 'id': $("#cities").val() },
function (data) {
$("#loca").html(data).show();
});
}
</script>
EDIT:
This is the generated HTML code
<select id="cities" name="cities" onselect="getLoca()"><option value="0">--City-- </option>
<option value="1">City1</option>
<option value="2">City2</option>
<option value="3">City3</option>
<option value="4">City4</option>
<option value="5">City5</option>
</select>;
<select id="loca" name="loca" style="width: 170px" ></select>
Use onchange instead of onselect.
jsFiddle Demo
onselect does not do what you expect - it fires when the user selects text (you know, by dragging the mouse or holding shift and using the arrow buttons), so it is not applicable to a select box, which has no selectable text. It works on certain input elements (like text) and textareas, or you can use it on the window.
onchange fires when the value of a form element changes - so this is what you need.
Note: using inline event handlers in your HTML is not a good idea most of the time. If you can, use addEventListener instead.

Manually Triggering Form Validation using jQuery

I have a form with several different fieldsets. I have some jQuery that displays the field sets to the users one at a time. For browsers that support HTML5 validation, I'd love to make use of it. However, I need to do it on my terms. I'm using JQuery.
When a user clicks a JS Link to move to the next fieldset, I need the validation to happen on the current fieldset and block the user from moving forward if there is issues.
Ideally, as the user loses focus on an element, validation will occur.
Currently have novalidate going and using jQuery. Would prefer to use the native method. :)
TL;DR: Not caring about old browsers? Use form.reportValidity().
Need legacy browser support? Read on.
It actually is possible to trigger validation manually.
I'll use plain JavaScript in my answer to improve reusability, no jQuery is needed.
Assume the following HTML form:
<form>
<input required>
<button type="button">Trigger validation</button>
</form>
And let's grab our UI elements in JavaScript:
var form = document.querySelector('form')
var triggerButton = document.querySelector('button')
Don't need support for legacy browsers like Internet Explorer? This is for you.
All modern browsers support the reportValidity() method on form elements.
triggerButton.onclick = function () {
form.reportValidity()
}
That's it, we're done. Also, here's a simple CodePen using this approach.
Approach for older browsers
Below is a detailed explanation how reportValidity() can be emulated in older browsers.
However, you don't need to copy&paste those code blocks into your project yourself — there is a ponyfill/polyfill readily available for you.
Where reportValidity() is not supported, we need to trick the browser a little bit. So, what will we do?
Check validity of the form by calling form.checkValidity(). This will tell us if the form is valid, but not show the validation UI.
If the form is invalid, we create a temporary submit button and trigger a click on it. Since the form is not valid, we know it won't actually submit, however, it will show validation hints to the user. We'll remove the temporary submit button immedtiately, so it will never be visible to the user.
If the form is valid, we don't need to interfere at all and let the user proceed.
In code:
triggerButton.onclick = function () {
// Form is invalid!
if (!form.checkValidity()) {
// Create the temporary button, click and remove it
var tmpSubmit = document.createElement('button')
form.appendChild(tmpSubmit)
tmpSubmit.click()
form.removeChild(tmpSubmit)
} else {
// Form is valid, let the user proceed or do whatever we need to
}
}
This code will work in pretty much any common browser (I've tested it successfully down to IE11).
Here's a working CodePen example.
You can't trigger the native validation UI (see edit below), but you can easily take advantage of the validation API on arbitrary input elements:
$('input').blur(function(event) {
event.target.checkValidity();
}).bind('invalid', function(event) {
setTimeout(function() { $(event.target).focus();}, 50);
});
The first event fires checkValidity on every input element as soon as it loses focus, if the element is invalid then the corresponding event will be fired and trapped by the second event handler. This one sets the focus back to the element, but that could be quite annoying, I assume you have a better solution for notifying about the errors. Here's a working example of my code above.
EDIT: All modern browsers support the reportValidity() method for native HTML5 validation, per this answer.
In some extent, You CAN trigger HTML5 form validation and show hints to user without submitting the form!
Two button, one for validate, one for submit
Set a onclick listener on the validate button to set a global flag(say justValidate) to indicate this click is intended to check the validation of the form.
And set a onclick listener on the submit button to set the justValidate flag to false.
Then in the onsubmit handler of the form, you check the flag justValidate to decide the returning value and invoke the preventDefault() to stop the form to submit. As you know, the HTML5 form validation(and the GUI hint to user) is preformed before the onsubmit event, and even if the form is VALID you can stop the form submit by returning false or invoke preventDefault().
And, in HTML5 you have a method to check the form's validation: the form.checkValidity(), then in you can know if the form is validate or not in your code.
OK, here is the demo:
http://jsbin.com/buvuku/2/edit
var field = $("#field")
field.keyup(function(ev){
if(field[0].value.length < 10) {
field[0].setCustomValidity("characters less than 10")
}else if (field[0].value.length === 10) {
field[0].setCustomValidity("characters equal to 10")
}else if (field[0].value.length > 10 && field[0].value.length < 20) {
field[0].setCustomValidity("characters greater than 10 and less than 20")
}else if(field[0].validity.typeMismatch) {
field[0].setCustomValidity("wrong email message")
}else {
field[0].setCustomValidity("") // no more errors
}
field[0].reportValidity()
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="email" id="field">
Somewhat easy to make add or remove HTML5 validation to fieldsets.
$('form').each(function(){
// CLEAR OUT ALL THE HTML5 REQUIRED ATTRS
$(this).find('.required').attr('required', false);
// ADD THEM BACK TO THE CURRENT FIELDSET
// I'M JUST USING A CLASS TO IDENTIFY REQUIRED FIELDS
$(this).find('fieldset.current .required').attr('required', true);
$(this).submit(function(){
var current = $(this).find('fieldset.current')
var next = $(current).next()
// MOVE THE CURRENT MARKER
$(current).removeClass('current');
$(next).addClass('current');
// ADD THE REQUIRED TAGS TO THE NEXT PART
// NO NEED TO REMOVE THE OLD ONES
// SINCE THEY SHOULD BE FILLED OUT CORRECTLY
$(next).find('.required').attr('required', true);
});
});
I seem to find the trick:
Just remove the form target attribute, then use a submit button to validate the form and show hints, check if form valid via JavaScript, and then post whatever. The following code works for me:
<form>
<input name="foo" required>
<button id="submit">Submit</button>
</form>
<script>
$('#submit').click( function(e){
var isValid = true;
$('form input').map(function() {
isValid &= this.validity['valid'] ;
}) ;
if (isValid) {
console.log('valid!');
// post something..
} else
console.log('not valid!');
});
</script>
Html Code:
<form class="validateDontSubmit">
....
<button style="dislay:none">submit</button>
</form>
<button class="outside"></button>
javascript( using Jquery):
<script type="text/javascript">
$(document).on('submit','.validateDontSubmit',function (e) {
//prevent the form from doing a submit
e.preventDefault();
return false;
})
$(document).ready(function(){
// using button outside trigger click
$('.outside').click(function() {
$('.validateDontSubmit button').trigger('click');
});
});
</script>
Hope this will help you
For input field
<input id="PrimaryPhNumber" type="text" name="mobile" required
pattern="^[789]\d{9}$" minlenght="10" maxLength="10" placeholder="Eg: 9444400000"
class="inputBoxCss"/>
$('#PrimaryPhNumber').keyup(function (e) {
console.log(e)
let field=$(this)
if(Number(field.val()).toString()=="NaN"){
field.val('');
field.focus();
field[0].setCustomValidity('Please enter a valid phone number');
field[0].reportValidity()
$(":focus").css("border", "2px solid red");
}
})
$('#id').get(0).reportValidity();
This will trigger the input with ID specified. Use ".classname" for classes.
When there is a very complex (especially asynchronous) validation process, there is a simple workaround:
<form id="form1">
<input type="button" onclick="javascript:submitIfVeryComplexValidationIsOk()" />
<input type="submit" id="form1_submit_hidden" style="display:none" />
</form>
...
<script>
function submitIfVeryComplexValidationIsOk() {
var form1 = document.forms['form1']
if (!form1.checkValidity()) {
$("#form1_submit_hidden").click()
return
}
if (checkForVeryComplexValidation() === 'Ok') {
form1.submit()
} else {
alert('form is invalid')
}
}
</script>
Another way to resolve this problem:
$('input').oninvalid(function (event, errorMessage) {
event.target.focus();
});

html5 form checkValidity() method not found

I am trying to use the form method checkValidity().
http://html5test.com/ tells me that my browser (Chrome) support the form-level checkValidity method.
However, using jsfiddle http://jsfiddle.net/LcgnQ/2/ I have tried the following html and javascript snippets:
<form id="profileform" name="profileform">
<input type="text" id="firstname" required>
<input type="button" id="testbutton" value="Test">
</form>
$('#testbutton').bind('click',function(){
try{
alert($('#profileform').checkValidity());
}
catch(err){alert('err='+err)};
});
I'm getting an error: object has no method checkValidity()
What am I doing wrong?
Try:
$('#profileform')[0].checkValidity()
When you select $('#profileform') you get a jQuery object array. To access actual DOM properties you must select the first item in the array, which is the raw DOM element.
#robertc 's Answer is perfect. Anyway I'd just add another way to do it using jQuery's .get([index]) function. It also retrieves the DOM element for the given index, or all of the matched DOM elements if there's no index declared.
In the end it is exactly the same, only written in a bit more verbose way:
$('#profileform').get(0).checkValidity()
Leaving you the docs right here: https://api.jquery.com/get/
Just another way:
// Fetch all the forms we want to apply custom Bootstrap validation styles to
var forms = document.getElementsByName('profileform');
// Loop over them and prevent submission
var validation = Array.prototype.filter.call(forms, function (form) {
form.addEventListener('submit', function (event) {
if (form.checkValidity() === false) {
event.preventDefault();
event.stopPropagation();
}
}, false);
});