How to set required to a custom select option? - javascript

I want to show message required when user don't set a choice.
This is my code:
var options = document.querySelectorAll('.myOptions');
var selecText = document.querySelector('.selectFeld>p');
var mylist = document.querySelector('.list_contrat');
//var iconSelect = document.querySelector(".icon_typeCont_rota");
var valueTypeContra = document.querySelector('#typecontrat');
for(option of options) {
option.onclick = function() {
mylist.classList.toggle('myhide');
//iconSelect.classList.toggle('myRotate');
selecText.innerHTML = this.textContent;
valueTypeContra.value = this.getAttribute('data-value'); // get value select option
}
}
<div class="selectFeld" title="Type de contrat">
<input type="text" name="typeContrat" id="typecontrat" class="d-none" required>
<p>Type de contrat</p>
<img src="icon_form/Icon_contrat_deroulant.png" alt="" class="icon_select">
</div>
<ul class="container-optionSelec list_contrat myhide">
<li class="myOptions" data-value="redaction"><p>Redaction</p></li>
<li class="myOptions" data-value="assistance"><p>Assistance</p></li>
</ul>
It's a custom select option, the code set the value for the input displayed none

Since you're not using a standard form element you're not able to use the standard required attribute, and therefore don't have the standard help features that goes along with it. And adding required to your input field does not present the built-in help message because you are hiding it.
You need to use Javascript to program a custom "required" message to go along with your custom form input mechanism. Naturally there are a number of ways to accomplish this, and present an error message to your user. What do you suppose works best for your users?
Upon first glance...
Remove the ineffective required attribute from the input element. Change the input to a hidden type, to avoid using css to hide it. And add a note to the instructions letting your users know ahead of time the selection is necessary to proceed.
Add a submit event handler to the form to capture submission and have an opportunity to validate the form. In the handler check the (now hidden) input field for an empty string indicating the custom selection mechanism has not been used. If the input value is empty, emphasize the instructions, and provide the user an error message.
For example:
var options = document.querySelectorAll('.myOptions');
var selecText = document.querySelector('.selectFeld>p');
var mylist = document.querySelector('.list_contrat');
var valueTypeContra = document.querySelector('#typecontrat');
for (option of options) {
option.onclick = function() {
selecText.style.color = 'black'; // restore black color to instruction
selecText.innerHTML = this.textContent;
valueTypeContra.value = this.getAttribute('data-value');
}
}
// GET FORM AND ADD SUBMIT EVENT HANDLER
document.querySelector('form').onsubmit = function () {
// check if "typeContrat" is equal to an empty string
if ( "" === this.elements['typeContrat'].value ) {
// emphasize the instruction label
selecText.style.color = 'red';
// provide the user and alert message
alert('Veuillez sélectionner type de contrat');
// prevent the form from being submitted
return false;
}
// if "typeContrat" is not an empty string submit the form
else { return true; }
}
<form>
<div class="selectFeld" title="Type de contrat">
<input type="hidden" name="typeContrat" id="typecontrat" class="d-none" value="">
<p>Type de contrat (required)</p>
</div>
<ul class="container-optionSelec list_contrat myhide">
<li class="myOptions" data-value="redaction">
<p>Redaction</p>
</li>
<li class="myOptions" data-value="assistance">
<p>Assistance</p>
</li>
</ul>
<input type="submit">
</form>
However, there are many user interface approaches and programming mechanisms to accomplish this, so first determine what works best for your users, supports your application purpose, goals, and look, meets your security needs—and do that.

Related

The form does not work correctly when sent

I wrote the code for a form validation.
Should work like this:
It checks (allLetter (uName)) and if it's true, then validate the next input.
If any validation is false then it should return false.
My problem is that if both validations are true, then everything is exactly false and the form is not sent.
If I set true in formValidation (), if at least one check false, the form should not be sent.
<form name='registration' method="POST" onSubmit="return formValidation();">
<label for="userName">Name:</label>
<input type="text" name="userName" size="20" />
<label for="userPhone">Phone:</label>
<input type="text" name="userPhone" size="20" />
<input type="submit" name="submit" value="Submit" />
</form>
function formValidation() {
var uName = document.registration.userName;
var uPhone = document.registration.userPhone;
if(allLetter(uName)) {
if(phone(uPhone)) {}
}
return false;
}
function phone(uPhone){
var digts = /^[0-9]+$/;
if(uPhone.value.match(digts)){
return true;
} else {
alert('Phone must have only digits');
uPhone.focus();
return false;
}
}
function allLetter(uName) {
var letters = /^[A-Za-z]+$/;
if(uName.value.match(letters)) {
return true;
}else{
alert('Username must have alphabet characters only');
uName.focus();
return false;
}
}
First, you are using a 20+ year old way to gain references to your elements (document.form.formElementNameAttributeValue) and, while this still works for legacy reasons, it doesn't follow the standard Document Object Model (DOM) API.
Next, you've broken up your validation tests into different methods (and that's certainly not a bad idea for reusability), but in this case is is adding a ton of code that you just don't need. I've always found it's best to start simple and get the code working, then refactor it.
You're also not using the <label> elements correctly.
One other point, your form is set to send its data via a POST request. POST should only be used when you are changing the state of the server (i.e. you are adding, editing or deleting some data on the server). If that's what your form does, you'r fine. But, if not, you should be using a GET request.
Lastly, you are also using a 20+ year old technique for setting up event handlers using inline HTML event attributes (onsubmit), which should no longer be used for many reasons. Additionally, when using this technique, you have to use return false from your validation function and then return in front of the validation function name in the attribute to cancel the event instead of just using event.preventDefault().
So, here is a modern, standards-based approach to your validation:
// Get references to the elements you'll be working with using the DOM API
var frm = document.querySelector("form[name='registration']");
var user = document.getElementById("userName");
var phone = document.getElementById("userPhone");
// Set up event handlers in JavaScript, not with HTML attributes
frm.addEventListener("submit", formValidation);
// Validation function will automatically be passed a reference
// the to event it's associated with (the submit event in this case).
// As you can see, the function is prepared to recieve that argument
// with the "event" parameter.
function formValidation(event) {
var letters = /^[A-Za-z]+$/;
var digts = /^[0-9]+$/;
// This will not only be used to show any errors, but we'll also use
// it to know if there were any errors.
var errorMessage = "";
// Validate the user name
if(user.value.match(letters)) {
// We've already validated the user name, so all we need to
// know now is if the phone is NOT valid. By prepending a !
// to the test, we reverse the logic and are now testing to
// see if the phone does NOT match the regular expression
if(!phone.value.match(digts)) {
// Invalid phone number
errorMessage = "Phone must have only digits";
phone.focus();
}
} else {
// Invalid user name
errorMessage = "Username must have alphabet characters only";
user.focus();
}
// If there is an error message, we've got a validation issue
if(errorMessage !== ""){
alert(errorMessage);
event.preventDefault(); // Stop the form submission
}
}
<!-- 20 is the default size for input elements, but if you do
want to change it do it via CSS, not HTML attributes -->
<form name='registration' method="POST">
<!-- The for attribute of a label must be equal to the id
attribute of some other element, not the name attribute -->
<label for="userName">Name:</label>
<input type="text" name="userName" id="userName">
<label for="userPhone">Phone:</label>
<input type="text" name="userPhone" id="userPhone">
<input type="submit" name="submit" value="Submit">
</form>

Getting focussed element immediately after focusout event

I have 2 text inputs which are related to each other and I need to validate once user tabs out of both the input text fields. This is a snapshot:
And the HTML counterpart:
<div class="four float_left field_div_wrapper">
<div class="padding_5">
<div class="field_title">
Telephon rumah
</div>
<div class="twelve height_30 land_phone_div">
<input type="text" id="telephon_rumah_field_1" class="three land_phone_field_1 land_phone_field">
<input type="text" id="telephon_rumah_field_2" class="eight land_phone_field_2 land_phone_field">
</div>
<div class="twelve float_left clear_left red_text display_hidden error_div_text">
This field must be numeric with 3 to 4 and 7 to 8 digits
</div>
</div>
</div>
My javascript code for validating the 2 text fields of land phone:
function performLandPhoneValidationOnDiv(landphoneDiv) {
var landPhoneValid = true;
// Here we consider both fields (code of area and office / home phone numbers) for validation if they are non-empty
// If both the fields are empty then it is a valid entry!
var areaCodeField = $(landphoneDiv).find(".land_phone_field_1");
var phoneField = $(landphoneDiv).find(".land_phone_field_2");
// We need to check current focus and perform validations only if both the text fields do not have focus currently
// http://stackoverflow.com/a/2684561/260665
// var phoneFieldsHasFocus = $(areaCodeField).is(":focus") || $(phoneField).is(":focus");
var phoneFieldsHasFocus = $(landphoneDiv).is(":focus");
if (!phoneFieldsHasFocus) {
.
.
.
// Internal validation to check if both the fields (area & phone) has valid data
}
return landPhoneValid;
}
And the code which triggers this validation is blur: (I have also tried focusout)
$(".land_phone_field").blur(function () {
performLandPhoneValidationOnDiv($(this).closest(".land_phone_div"));
});
Problem: As you can see in the first image, as soon as I tab out from first field, validation is triggered even before user attempts to enter something in the second section of the phone field.
To avoid this I have tried the following in the performLandPhoneValidationOnDiv callback after the event is triggered:
var phoneFieldsHasFocus = $(areaCodeField).is(":focus") || $(phoneField).is(":focus");
And:
var phoneFieldsHasFocus = $(landphoneDiv).is(":focus");
Both return false as result. I suspect this is so because the blur / focusout event is triggered as soon as I tab out and even before any other element gains focus. For the same reason I tried to see if the parent contains focus in the interim by any chance, it seems not to be the case.
I can handle this situation by using booleans and set the state when user tabs out of both the fields to perform validation, but it would not be a clean solution and I want to know the best way to handle such situations.

MVC4: Show validation error on the form or summary instead of an input?

I'm trying to leverage some form validation to do something it really wasn't designed to do. I have a table in my form and each row has a checkbox. I want to ensure that at least one of a specific type of checkbox is selected, if not I want to show a validation error. I am doing something similar with a text box with logic that looks like this:
function ValidateName() {
var $nameTextbox = $("#Name");
var $originalName = $("#OriginalName");
var nameText = $nameTextbox.val().toLowerCase();
var originalNameText = $originalName.val().toLowerCase();
//check to see if original name and group name match
if (nameText != originalNameText) {
//This isn't the same name we started with
if (uniqueNames.indexOf(nameText) > -1) {
//name isn't unique, throw validation error
var currentForm = $nameTextbox.closest("form");
//trigger validation
var errorArray = {};
errorArray["Name"] = 'Name must be unique';
currentForm.validate().showErrors(errorArray);
}
}
}
I've written something similar for the table and it works as long as I point the errorArray's index to the id of an input. However, I want to display the error somewhere more generic like the validation summary at the top of the form. How do I set up the error array to show on the form or the validation summary instead of a specific input? Is that even possible?
One way you could do this is you set a hidden input that is false when none are check and true if 1 or more are checked. You then listen to all the checkboxes by giving them all a class. I have an example shown below
http://jsfiddle.net/95acw2m9/
Html
<input type="hidden" id="IsCheckValue" name="IsCheckedValue" value="false"/>
<input type="checkbox" class="someCheckbox"/>
<input type="checkbox" class="someCheckbox"/>
<input type="checkbox" class="someCheckbox"/>
Jquery
$(document).ready(function(){
$(".someCheckbox").change(function(){
if($(".someCheckbox:checked ").length > 0){
$("#IsCheckValue").val("True")
}else{
$("#IsCheckValue").val("False")
}
})
})
Then pass that bool value in your model. In your controller method you can check the value of the bool. If the bool is false set the model to false like this
ModelState.AddModelError("Checkbox", "Must select one checkbox");
You can use the #Html.ValidationSummary() to display the error in your view.

HTML5/JS/jQuery: On invalid input, mark a different (arbitrary) element as invalid

I am trying to create one of those standard new password forms, where you type the new password once and then a second time to confirm. I would like it so that once you blur away from these fields, if they don't match, both will be marked invalid, as in the following scenario:
User enters password abc into #newpassword1.
User tabs to #newpassword2.
User enters password def into #newpassword2.
User tabs away.
Validation detects a mismatch, and marks both #newpassword1 and #newpassword2 as invalid.
I know that i can mark the target of an event as invalid by using e.target.setCustomValidity(...), but i don't understand JavaScript's event model very well and can't figure out how to mark a different element as invalid based on the event target's own invalidity.
This is the relevant excerpt of (non-working) code that i am trying to use:
if ( $('#newpassword1').val() != $('#newpassword2').val() ) {
errorMessage = "The new passwords you've entered don't match.";
$('#newpassword1, #newpassword2').setCustomValidity(errorMessage);
}
This seems like it should work, intuitively, but of course it does not. The error is simply TypeError: $(...).setCustomValidity is not a function.
Please note: I am not asking how to add a red ring or whatever to a field, i want it to actually be invalid (as in, have its validity.valid property return false).
Is it possible to do this?
Thanks!
Try the below code. You are getting that error because jQuery returns an array of selected objects and since setCustomValidity is supported by native input elements and not jquery objects, you are seeing that error.
$('#newpassword1, #newpassword2').each(function() {
this.setCustomValidity(errorMessage)
});
<div class="cabinet_settings_header cabinet_header">Список регионов работы для выбора</div>
<div class="registration_region_select checkbox-group required">
<?for($i = 0; $i < sizeof($regions); $i++):?>
<label for="region_id_<?=$regions[$i]['region_id']?>">
<input type="checkbox" name="region_id[]" value="<?=$regions[$i]['region_id']?>" id="region_id_<?=$regions[$i]['region_id']?>" />
<?=$regions[$i]['name']?>
</label>
<?endfor;?>
</div>
<div class="cabinet_settings_header cabinet_header">Проверка выбора регионов работы (разрешмет отправку формы, если минимум 1 выбран)</div>
$('.checkbox-group.required input').on('change', function(){
checkRegions();
});
function checkRegions(){
checked_counter = $('.checkbox-group.required :checkbox:checked').length;
if(checked_counter > 0){
$('.checkbox-group.required #region_id_2')[0].setCustomValidity('');
}else{
$('.checkbox-group.required #region_id_2')[0].setCustomValidity('Выберите хотябы 1 из вариантов');
}
}
$(document).ready(function() {
checkRegions();
$("form").submit(function(event){
if($('.checkbox-group.required :checkbox:checked').length <= 0 ){
$('.checkbox-group.required #region_id_2').focus();
event.preventDefault();
}
})
});

AngularJS: How do I manually set input to $valid in controller?

Using the TokenInput plugin and using AngularJS built-in formController validation.
Right now I'm trying to check if the field contains text, and then set field to valid if it does. The issue with using the plugin is it creates it's own input and then a ul+li for stlying.
I have access to addItem (formname) and my capablities in the controller, I just need to set it to $valid.
Markup.
<form class="form-horizontal add-inventory-item" name="addItem">
<input id="capabilities" name="capabilities" token-input data-ng-model="inventoryCapabilitiesAutoComplete" data-on-add="addCapability()" data-on-delete="removeCapability()" required>
<div class="required" data-ng-show="addItem.capabilities.$error.required" title="Please enter capability."></div>
</form>
JS.
$scope.capabilityValidation = function (capability) {
if (capability.name !== "") {
addItem.capabilities.$valid = true;
addItem.capabilities.$error.required = false;
} else {
addItem.capabilities.$valid = false;
addItem.capabilities.$error.required = true;
}
};
I'm running the capabilityValidation function when TokenInput has something entered and passing in the object.
EDIT:
Found out ng-model on my input does stuff and gets the autocomplete results, which is why I can't get ng-valid to work since it's based on the model.
$scope.inventoryCapabilitiesAutoComplete = {
options: {
tokenLimit: null
},
source: urlHelper.getAutoComplete('capability')
};
I didn't write this autocomplete implementation, is there another way to do this where I would have access to the ng-model attr and move the model function somewhere else?
You cannot directly change a form's validity. If all the descendant inputs are valid, the form is valid, if not, then it is not.
What you should do is to set the validity of the input element. Like so;
addItem.capabilities.$setValidity("youAreFat", false);
Now the input (and so the form) is invalid.
You can also see which error causes invalidation.
addItem.capabilities.errors.youAreFat == true;
The answers above didn't help me solve my problem. After a long search I bumped into this partial solution.
I've finally solved my problem with this code to set the input field manually to ng-invalid (to set to ng-valid set it to 'true'):
$scope.myForm.inputName.$setValidity('required', false);
I came across this post w/a similar issue.
My fix was to add a hidden field to hold my invalid state for me.
<input type="hidden" ng-model="vm.application.isValid" required="" />
In my case I had a nullable bool which a person had to select one of two different buttons. if they answer yes, an entity is added to the collection and the state of the button changes. Until all of the questions get answered, (one of the buttons in each of the pairs has a click) the form is not valid.
vm.hasHighSchool = function (attended) {
vm.application.hasHighSchool = attended;
applicationSvc.addSchool(attended, 1, vm.application);
}
<input type="hidden" ng-model="vm.application.hasHighSchool" required="" />
<div class="row">
<div class="col-lg-3"><label>Did You Attend High School?</label><label class="required" ng-hide="vm.application.hasHighSchool != undefined">*</label></div>
<div class="col-lg-2">
<button value="Yes" title="Yes" ng-click="vm.hasHighSchool(true)" class="btn btn-default" ng-class="{'btn-success': vm.application.hasHighSchool == true}">Yes</button>
<button value="No" title="No" ng-click="vm.hasHighSchool(false)" class="btn btn-default" ng-class="{'btn-success': vm.application.hasHighSchool == false}">No</button>
</div>
</div>
It is very simple. For example :
in you JS controller use this:
$scope.inputngmodel.$valid = false;
or
$scope.inputngmodel.$invalid = true;
or
$scope.formname.inputngmodel.$valid = false;
or
$scope.formname.inputngmodel.$invalid = true;
All works for me for different requirement. Hit up if this solve your problem.
to get this working for a date error I had to delete the error first before calling $setValidity for the form to be marked valid.
delete currentmodal.form.$error.date;
currentmodal.form.$setValidity('myDate', true);

Categories