Required attribute to be shown visually - javascript

I have a form where some fields are required, and some others aren't.
Now:
Does Polymer provide any "out-of-the-box" way to mark an element as "required"?
If not, what's the best way, in CSS, to show that a field is required?
At the moment, once the form is submitted the required fields will be shown as such. However, this happens after the form is submitted (or attempted).
I would like the user to know that while the first name is required, the middle name isn't.
Am I missing something very obvious?

One way would be to use attribute prefix or suffix
<paper-input label="First Name">
<div prefix>*</div>
<div suffix>*</div>
</paper-input>
Another way would be to create a new input element
<span hidden={{!required}} class="required"> * </span>
<paper-input-container no-label-float="[[noLabelFloat]]"
always-float-label="[[_computeAlwaysFloatLabel(alwaysFloatLabel,placeholder)]]"
auto-validate$="[[autoValidate]]"
disabled$="[[disabled]]"
invalid="[[invalid]]">
But this does not make sense only for required field as you will have to emulate/copy the complete paper-input code

Here is basic example how I'm validating the inputs: Plunk
On each input change call the validation method,
if it passes - submit the form.
<paper-input
id="step"
type="number"
min="1"
max="10"
value="{{value}}"
editable
required
auto-validate="true"
invalid="{{invalid}}"
preventInvalidInput
error-message="value: {{value}} - means invalid is {{invalid}}"
on-change="stepChange">
</paper-input>
stepChange: function(e, detail) {
//validation code
//Fields must be revalidated on each change
var step = this.$.step;
var val_step = step.validate();
// if alll the inputs are valid then submit the form
if ( false == val_step )
{
console.log("not invalid");
}
else
{
console.log("invalid");
}
},

Related

Bootstrap validation conflicts

I am using Vue.js and Bootstrap to design a website. I have a form that I am trying to run my custom validation on. It works fine until the user clicks submit which adds the was-validated class to the form per the bootstrap documentation.
At this point any required input field that has any input whether it meets my custom validation or not is marked as valid and gets a green border and check mark. My custom validation is still being run and displaying b-form-invalid-feedback correctly. However, it seems that was-validated is marking fields with the required prop as valid while not taking my custom validation into account this is leading to conflicting validation as a field has a green check mark (because it satisfies the required property) but still an error message because it is not yet valid per my custom validation.
I have tried removing the :valid style this isn't the effect I want as I do want it to display those styles when it is valid per my validation. Hope this makes sense if not I will provide pictures. I also have a second issue I have a date picker that is not displaying b-form-invalid-feedback at all even when was-validated is added.
My Code
<b-form #submit.prevent="addReview" name="review-form" novalidate>
<div class="name">
<label class="sr-only" for="form-input-name">Name</label>
<b-input id="form-input-name" class="form-inputs mb-2 mr-sm-2 mb-sm-0" v-model="name" placeholder="Name" required :state="isStateValid(this.name)"></b-input>
<b-form-invalid-feedback id="form-input-name">
You must enter a name
</b-form-invalid-feedback>
</div>
<div class="date">
<label class="sr-only" for="example-datepicker">Choose a date</label>
<b-form-datepicker id="datepicker" v-model="dateVisited" class="mb-2" required placeholder="Date Visited" :state="isStateValid(this.dateVisited)"></b-form-datepicker>
<b-form-invalid-feedback id="datepicker">
You must enter a valid date
</b-form-invalid-feedback>
</div>
<div class="service">
<label class="sr-only" for="form-input-service">Service Provided</label>
<b-input id="form-input-service" class="form-inputs mb-2" placeholder="Service Provided" v-model="service" required :state="isStateValid(this.service)"></b-input>
<b-form-invalid-feedback id="form-input-service">
You must enter the service provided
</b-form-invalid-feedback>
</div>
<div class="email">
<label class="sr-only" for="inline-form-input-username">Email</label>
<b-input id="inline-form-input-username" class="form-control mb-2 mr-sm-2 mb-sm-0" placeholder="Email" v-model="email" required :state="emailStateValidation"></b-input>
<b-form-invalid-feedback id="inline-form-input-username">
You must enter the part of your email that comes before the '#' symbol
</b-form-invalid-feedback>
</div>
<div class="domain">
<label class="sr-only" for="inline-form-input-domain">Domain</label>
<b-input-group prepend="#" class="mb-2 mr-sm-2 mb-sm-0">
<b-input id="inline-form-input-domain" placeholder="Domain ex: gmail.com" v-model="domain" required :state="domainStateValidation"></b-input>
<b-form-invalid-feedback id="inline-form-input-domain">
You must enter the part of your email that comes after the '#' symbol
</b-form-invalid-feedback>
</b-input-group>
</div>
<div class="description">
<label class="sr-only" for="textarea-rows">Describe Your Experience</label>
<b-form-textarea class="mb-3 mr-sm-2 mb-sm-0" id="textarea-rows" placeholder="Describe Your Experience" rows="4" required v-model="description" :state="isStateValid(this.description)"></b-form-textarea>
<b-form-invalid-feedback id="textarea-rows">
You must enter a description of your experience
</b-form-invalid-feedback>
</div>
<b-button type="submit">Save</b-button>
</b-form>
computed: {
emailStateValidation() {
if (this.email) {
return this.emailIsValid() ? true : false;
}
return null;
},
domainStateValidation() {
if (this.domain) {
return this.domainIsValid() ? true : false;
}
return null;
},
},
methods: {
emailIsValid() {
let regEx = /^(?!.*#)((^[^\.])[a-z0-9\.!#$%&'*+\-\/=?^_`{|}~"]*)*([^\.]$)/;
return regEx.test(this.email);
},
domainIsValid() {
let regEx = /((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return regEx.test(this.domain);
},
isStateValid(variable) {
if (variable) {
return variable.length > 0 ? true : false;
}
return null;
},
addReview() {
let mainForm = document.getElementsByName("review-form")[0];
mainForm.classList.add("was-validated");
...
Questions
Resolve the conflict between required and my custom validation
causing input fields being prematurely marked as valid
Display b-form-invalid-feedback on datepicker on form submit if
date is not selected
In a nutshell, remove novalidate from <form> in your Vue template. When you set novalidate, the inputs will remain in their :valid state throughout their lifecycle until you explicitly call setCustomValidity. Working Sandbox
Since, Bootstrap styles also apply to :valid or :invalid states so, even if your custom validators determine inputs to be invalid, both valid and invalid styles will get applied i.e. :valid and .is-invalid but, I guess it's just happens so, that :valid styles take precedence the way Bootstrap stylesheet is currently written.
U̶s̶e̶ ̶̶n̶o̶v̶a̶l̶i̶d̶a̶t̶e̶̶ ̶w̶h̶e̶n̶ ̶y̶o̶u̶'̶r̶e̶ ̶i̶m̶p̶l̶e̶m̶e̶n̶t̶i̶n̶g̶ ̶a̶ ̶c̶o̶m̶p̶l̶e̶t̶e̶ ̶v̶a̶l̶i̶d̶a̶t̶i̶o̶n̶ ̶s̶o̶l̶u̶t̶i̶o̶n̶ ̶y̶o̶u̶r̶s̶e̶l̶f̶ ̶i̶n̶c̶l̶u̶d̶i̶n̶g̶ ̶̶r̶e̶q̶u̶i̶r̶e̶d̶̶ ̶v̶a̶l̶i̶d̶a̶t̶o̶r̶.̶
With Bootstrap, since it also applies styles to :valid or :invalid states of input, you're better off NOT using novalidate.
Ofcourse, this will enable browser popups asking for filling certain fields which might be unwanted.
Suggestion: Use validated prop on your form and bind it to your form's state and set it to true in addReview(), it will automatically add was-validated class and you don't need to manipulate the DOM directly.
EDIT: Since removing novalidate enables browser validation, submit event no longer fired on the form and hence, was-validated class is never added to the form. This presented an issue in my original answer because messages and icon were not shown without was-validated. I have modified the sandbox to suggest a fix for that and that is to bind click event to submit button for validation logic and using submit event for stuff that should happen after successful validation.
EDIT for Datepicker: The reason why datepicker never invalidated was because of an issue in isStateValid() method specifically the part:
if(variable) { // "" evaluates to false
// ...
}
Since "" evaluates to false, it will always return null. The fix for that is in combination with the suggestion above of maintaining validated state for the form. Now, instead of checking if(variable), we check if(this.validated) and if it is true, we simply check the length and return either true or false.
Fundamentally was-validated is not bootstrap-vue native, it's browser native, which also has no understanding of :state. If you want to use was-validated you can't use custom validations. If you want to use custom validations. See the suggestion For 2. Which is basically, use another variable to control whether validation should be applied.
From the documentation on bootstrap-vue
When set, adds the aria-required="true" attribute on the component. Required validation needs to be handled by your application
You need to explicitly check that the validation should show, it isn't clear from the documentation what required actually does, but it doesn't affect validation. Which explains why that part isn't working. Personally I set a global this.showValidations = true on submit, so that the validations actually run at the right time and not before (and after when expected). In your case, you can check for the was-validated class that you are adding explicitly. It isn't great, but it seems it must be done here.

prevent blank form submission

If I want to prevent my form to be submitted if the fields are blank and highlight the blank fields.The code I have so far works if I try to submit when it is blank but doesnt submit if the fields are filled. I cannot seem to figure out what I am doing wrong. Please help
JavaScript code:
function CheckFields(){
if((document.getElementById('title').value=="") || (document.getElementById("textfield").value=="")){
const element = document.querySelector('form');
element.addEventListener('submit',event =>{
event.preventDefault();
alert("Fill the form to be submitted");
document.getElementById("title").style.backgroundColor=red;
document.getElementById("title").style.backgroundColor=red;
});
}
HTML:
<input name="post" type="submit" value="Post" onclick="CheckFields();">
Re-posted from: https://developer.mozilla.org/en-US/docs/Learn/Forms/Form_validation for the purposes of having the a static answer to this question, as the webpage may change
Using built-in form validation
One of the most significant features of HTML5 form controls is the ability to validate most user data without relying on JavaScript. This is done by using validation attributes on form elements. We've seen many of these earlier in the course, but to recap:
required: Specifies whether a form field needs to be filled in before the form can be submitted.
minlength and maxlength: Specifies the minimum and maximum length of textual data (strings)
min and max: Specifies the minimum and maximum values of numerical input types
type: Specifies whether the data needs to be a number, an email address, or some other specific preset type.
pattern: Specifies a regular expression that defines a pattern the entered data needs to follow.
In general that is a wrong way to validate fields, but anyhow your error is the order of the condition and form submit event. So it should be like this:
var myForm = document.querySelector('form');
var myTitle = document.getElementById('title');
var myTextfield = document.getElementById('textfield');
myForm.addEventListener('submit', event=>{
if(myTitle.value=="" || myTextfield.value==""){
alert("Fill the form to be submitted");
myTitle.style.backgroundColor=red;
myTextfield.style.backgroundColor=red;
return false;
} else {
return true;
};
});
You can add required to input fields for client-side validation. For more advanced validation, you may want to add server-side validation via a model.
See required in action:
<form action="/action_page.php">
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname" value="" required><br>
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname" value="Doe"><br><br>
<input type="submit" value="Submit">
</form>
You can validate a form in many ways. In Html 5 form you can add required for client side validation. You can also validate form from server side. And you can also use ajax for realtime form validation. Use focus on the field.. to highlight a field that is not filled.

Angular is automatically adding 'ng-invalid' class on 'required' fields

I am building an angular app for which I have some forms set up.
I have some fields that are required to be filled before submission. Therefore I have added 'required' on them:
<input type="text" class="form-control" placeholder="Test" ng-model="data.test" required>
However when I launch my app, the fields are displayed as 'invalid' and the classes 'ng-invalid' and 'ng-invalid-required' even before the submit button has been click or before the user has typed anything in the fields.
How can I make sure that thoses 2 classes are not added immediately but either once the user has submitted the form or when he has typed something wrong in the corresponding field?
Since the inputs are empty and therefore invalid when instantiated, Angular correctly adds the ng-invalid class.
A CSS rule you might try:
input.ng-dirty.ng-invalid {
color: red
}
Which basically states when the field has had something entered into it at some point since the page loaded and wasn't reset to pristine by $scope.formName.setPristine(true) and something wasn't yet entered and it's invalid then the text turns red.
Other useful classes for Angular forms (see input for future reference )
ng-valid-maxlength - when ng-maxlength passes
ng-valid-minlength - when ng-minlength passes
ng-valid-pattern - when ng-pattern passes
ng-dirty - when the form has had something entered since the form loaded
ng-pristine - when the form input has had nothing inserted since loaded (or it was reset via setPristine(true) on the form)
ng-invalid - when any validation fails (required, minlength, custom ones, etc)
Likewise there is also ng-invalid-<name> for all these patterns and any custom ones created.
Thanks to this post, I use this style to remove the red border that appears automatically with bootstrap when a required field is displayed, but user didn't have a chance to input anything already:
input.ng-pristine.ng-invalid {
-webkit-box-shadow: none;
-ms-box-shadow: none;
box-shadow:none;
}
Since the fields are empty they are not valid, so the ng-invalid and ng-invalid-required classes are added properly.
You can use the class ng-pristine to check out whether the fields have already been used or not.
Try to add the class for validation dynamically, when the form has been submitted or the field is invalid. Use the form name and add the 'name' attribute to the input. Example with Bootstrap:
<div class="form-group" ng-class="{'has-error': myForm.$submitted && (myForm.username.$invalid && !myForm.username.$pristine)}">
<label class="col-sm-2 control-label" for="username">Username*</label>
<div class="col-sm-10 col-md-9">
<input ng-model="data.username" id="username" name="username" type="text" class="form-control input-md" required>
</div>
</div>
It is also important, that your form has the ng-submit="" attribute:
<form name="myForm" ng-submit="checkSubmit()" novalidate>
<!-- input fields here -->
....
<button type="submit">Submit</button>
</form>
You can also add an optional function for validation to the form:
//within your controller (some extras...)
$scope.checkSubmit = function () {
if ($scope.myForm.$valid) {
alert('All good...'); //next step!
}
else {
alert('Not all fields valid! Do something...');
}
}
Now, when you load your app the class 'has-error' will only be added when the form is submitted or the field has been touched.
Instead of:
!myForm.username.$pristine
You could also use:
myForm.username.$dirty
the accepted answer is correct.. for mobile you can also use this (ng-touched rather ng-dirty)
input.ng-invalid.ng-touched{
border-bottom: 1px solid #e74c3c !important;
}

How do I use jQuery validation plugin to validation a collection of strings?

I have a Java (Spring MVC) bean that has a collection of strings as a bean property. I can render these in the Freemarker something like this:
[#list listOfStrings as aString]
<input name="${fieldName}[${aString_index}]" type="text" value="${(currentValue!'')?html}" maxlength="50"/>
[/#list]
That gives me a series of input fields named as "aString[n]", which correctly get passed into the List on the serverside.
This was a single String field and I've recently moved to having a collection. How can I modify my jQuery validation plugin plugin to validate each instance of that field and display validation messages as appropriate for each field?
Current validation stuff using syntax like this:
$('#myform').validate({
rules: {
aString: {
minlength: 16
}
},
messages: {
aString: {
minLength: "failed validation"
}
}
});
I need to be able to reference the collection of strings (aString[0], aString[1] .... etc) and render a message so the user knows which of those instances are in error.
For a min-size validation you don't need to create a new Rule, just mark your fields with minlength='16' and make sure they have ID and NAME, and that they have a label for then:
[#list listOfStrings as aString]
<label for="${fieldName}_${aString_index}">String: </label>
<input name="${fieldName}_${aString_index}" name="${fieldName}_${aString_index}" type="text" value="${(currentValue!'')?html}" maxlength="50" minlength="16"/>
[/#list]
And then, you call:
$("#myform").validate();
I ended up defining custom methods and applying them using a class. This meant I had to add a
<label for="xyz" class="error" />
element in the appropriate place in the HTML.
$.validator.addMethod("codeRequired", $.validator.methods.required,"Please enter a code");
$.validator.addMethod("codeMinLength", $.validator.methods.minlength, $.format("The code appears to be too short, Please enter a valid {0} digit code."));
$.validator.addClassRules("code", { codeRequired: true, codeMinLength: 16 });
I then add a class="code" to my input fields I want validating.
This appears to work, I'll update later if I find issues with this solution.

Assign the value to different field ID?

I have a form with a unique identifier field that the user needs to enter, when passing this value it needs to appear in different field id. so for instance. the field that user enters the unique code in is called "unique" and the copy needs to be in "message", how can i achieve that?
<div data-role="fieldcontain">
<label for="pins" id="pinLabel"><span style="color:#f22300">*</span> Unique Code:</label>
<input data-mini="true" name="pins_r" id="pins" placeholder="9 alphanumeric characters"/>
</div>
<input type="hidden" id="msg" name="msg" value=pins>
Thanks
There are two ways to do this with JavaScript.
Method 1)
Have an onchange event on the unique field such that whenever the value is changed, change it in a hidden field called message.
<input type="text" id="unique" name="unique" onchange="setMessage(this);">
<input type="hidden" id="message" name="message">
function setMessage(field) {
document.getElementById('message').value = field.value;
}
Method 2)
Use ajax to post the form instead, that way you can build the fields yourself.
ie. post message= document.getElementById('unique').value
Both the above are greatly improved if you use JQuery or another JS helper framework.
If you want your values to be set in the label at the same time, it is entered.
You can do some thing like this.
$(document).ready(function() {
$('#pins').keypress(function() {
setTextValueForPins(this);
});
});
function setTextValueForPins(textPin)
{
$('#pinLabel').text($('#textPin').val());
}
If you want the value to be set after the user have entered the value, you can use the change event.
PS: Not tested the code , let me know if you face any Issues.

Categories