I am using abide from foundation zurb to validate inputs from the client side. I have 4 input fields that are being validated through js. I am using jquery to count .error after submit button click but I am getting unexpected values returned. After clicking the submit button twice the number of .errors shows count 8 even if there is only just 4 .errors fields. How can I display number of .errors that are visible in the form? LINK
<script>
var $error_items = 0;
$("#submit").click(function(e){
$error_items = $(".error").length;
alert($error_items);
});
</script>
HMTL
<form data-abide>
<div class="name-field">
<label>Your name <small>required</small>
<input type="text" required pattern="[a-zA-Z]+">
</label>
<small class="error">Name is required and must be a string.</small>
</div>
<div class="name-field">
<label>User name <small>required</small>
<input type="text" name="users_name" required pattern="[a-zA-Z]+">
</label>
<small class="error">Username is required and must be a string.</small>
</div>
<div class="email-field">
<label>Email <small>required</small>
<input type="email" required>
</label>
<small class="error">An email address is required.</small>
</div>
<div class="password-field">
<label>Password <small>required</small>
<input type="password" id="password" required pattern="password">
</label>
<small class="error">Your password must match the requirements</small>
</div>
<button type="submit" id="submit">Submit</button>
</form>
If you inspect the DOM after clicking the submit button, you will see the following for each of your error labels:
<label class="error"></label>
<small class="error"></small>
One added by you initially and the other added dynamically once the submit button is clicked. The count of 8 is correct.
You may just want to count label.error as that seems to be what you are trying to count.
You may count only the visible error labels using visible selector for instance:
$('small.error:visible').length
Related
I have 2 forms reservation info form & customer info form.
I've set all of the input fields as required.
I also have a button that is only supposed to hide the first form and show the second once clicked. I have it as type="button" since I'm not really submitting it anywhere.
I created a jQuery click() handler for my button.
My Issue is that I've tested the button and it completely bypasses the required validation of the input fields. It shows the second form and hides the first regardless of empty input fields.
I would like it if the forms validated the required attribute, so there are no blank input fields before they hide/show.
script.js
$(function () {
$('#reservation-submit-btn').click(function () {
$('#reservation-info-form').hide('slow');
$('#customer-info-form').show('slow');
})
})
HTML file
<div id="reservation-info-form" class="reservation-form-wrapper" aria-labelledby="reservation-form-label">
<div id="reservation-form-label"><h2>Make A Reservation</h2></div>
<form id="reservation-form" aria-label="reservation form" method="post" autocomplete="off">
<label for="res-date"></label>
<input
aria-label="reservation date"
type="date"
name="res-date"
id="res-date"
placeholder="current date"
required
/>
<label for="res-time"></label>
<input
aria-label="reservation time"
type="time"
name="res-time"
id="res-time"
placeholder="current time"
required
/>
<label for="res-party-size"></label>
<input
aria-label="party size"
type="number"
min="1"
max="9"
name="res-party-size"
id="res-party-size"
placeholder=0
required
/>
<button type="button" id="reservation-submit-btn" class="submit-btn">
Find a Table
</button>
I realize that creating a click handler just adds a method to the button and doesn't consider all of the input fields or the required attributes. So my real question is how do I do this in a way where I create the effects I need from the button while not bypassing the required attribute on the input fields?
You can use a library called jQuery Validation. It has built-in functions for auto-validate the forms. Also you have to change the type of your button from type=button to type=submit
$("#reservation-info-form").validate({
submitHandler: function(form) {
$('#reservation-info-form').hide('slow');
$('#customer-info-form').show('slow');
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery-validation#1.19.5/dist/jquery.validate.min.js"></script>
<div id="reservation-info-form" class="reservation-form-wrapper" aria-labelledby="reservation-form-label">
<div id="reservation-form-label">
<h2>Make A Reservation</h2>
</div>
<form id="reservation-form" aria-label="reservation form" method="post" autocomplete="off">
<label for="res-date"></label>
<input aria-label="reservation date" type="date" name="res-date" id="res-date" placeholder="current date" required />
<label for="res-time"></label>
<input aria-label="reservation time" type="time" name="res-time" id="res-time" placeholder="current time" required />
<label for="res-party-size"></label>
<input aria-label="party size" type="number" min="1" max="9" name="res-party-size" id="res-party-size" placeholder=0 required />
<button id="reservation-submit-btn" class="submit-btn" type="submit">
Find a Table
</button>
</form>
</div>
I have a login form with 2 input field and login button, one of the input field has email pattern for valid emails. If one of the input fields are empty then login button is becoming disabled. But my problem is that in case of wrong email pattern is entered, error message appears but the button does not become disable.
Here is the scenario:
here is my template code for this part:
<form #loginForm="ngForm" (ngSubmit)="loginUser()">
<div class="form-group">
<label for="email">Email address:</label>
<input type="email" required #email="ngModel" class="input-field-background form-control" [class.is-invalid]="email.invalid && email.touched" [(ngModel)]="user.email" pattern="^\w+#[a-zA-Z_]+?\.[a-zA-Z]{2,3}$" [ngModelOptions]="{standalone: true}">
</div>
<div *ngIf="email.errors && (email.invalid && email.touched)">
<small class="error-text" *ngIf="email.errors.required">Email is required</small>
<small class="error-text" *ngIf="email.errors.pattern">Enter a valid email</small>
</div>
<div class="form-group">
<label for="password">Password:</label>
<input #password="ngModel" required type="password" [class.is-invalid]="password.invalid && password.touched" class="input-field-background form-control" [(ngModel)]="user.password" [ngModelOptions]="{standalone: true}">
<small class="error-text" [class.d-none]="password.valid || password.untouched">Password is required</small>
</div>
<small class="error-text">{{msg}}</small>
<div>
<button type="submit" class="login-button btn btn-info" [disabled] = "!user.email || !user.password">Login</button>
<small class="small-style float-right" [routerLink]="['/registration']">New User ? Register here</small>
</div>
</form>
How can I solve this problem ? Is there a way to solve that simply on template file or should I make some operations on the corresponding .ts file like assigning a new variable or a boolean etc...
#Chris Garsonn, you can check email validation in your submit button.
[disabled] = "!user.email || email.invalid || !user.password"
I have a form. In which I have input fields and I am doing some validation based on input. Also, there is a submit button which enables only if form is valid.
In this form I am enabling/disabling input field in one of the flow.
Initially, when the fields are enable and empty, create button is disabled. After i disable and enable the fields, create button becomes enabled. Although input fields are still empty.
More over button which is enabling/disabling this part is outside of this form.
Here is my code
`
<form method="post" novalidate id="example-widgets-form" name="mdnsCtrl.createSubDomainForm" valdr-type="SubDomain">
<div>
<label>Domain Name</label>
<input required type="text" name="subDomainName" placeholder="Domain Name" ng-model="mdnsCtrl.newDomain.name">
</div>
<div>
<label>Description</label>
<input type="text" name="subDomainDescription" placeholder="Description (Optional)" ng-model="mdnsCtrl.newDomain.description">
</div>
<button type="button" aria-label="Create" ng-click="mdnsCtrl.createDomain();"
ng-disabled="mdnsCtrl.createSubDomainForm.$invalid">
<span class="ng-scope">Create</span>
</button>
</div>
</form>
Tried few things like using $setUntouched() and $setPristine(). But nothing is working. Any help will be appreciated.
Adding a codepen example for this: code
Much Thanks.
`
Its not good practice to mix Angular with jQuery. Please read this great post: “Thinking in AngularJS” if I have a jQuery background?
You can easily achieve requested behavior by using ng-disabled="mdnsCtrl.formDisabled"
JS
var ctrl = this;
ctrl.formDisabled = false;
this.disable = function(){
ctrl.formDisabled = true;
};
this.enable = function(){
ctrl.formDisabled = false;
};
HTML
<div>
<label>Domain Name</label>
<input class="input-field" required type="text" name="subDomainName" placeholder="Domain Name"
ng-disabled="mdnsCtrl.formDisabled"
ng-model="mdnsCtrl.name" >
</div>
<div>
<label>Description</label>
<input class="input-field" type="text" name="subDomainDescription"
ng-disabled="mdnsCtrl.formDisabled"
placeholder="Description (Optional)" ng-model="mdnsCtrl.description">
</div>
Fixed Demo Codepen
I think you missed required attribute for Description input..
<input type="text" name="subDomainDescription" required ng-model="mdnsCtrl.newDomain.description">
I have optin popup of two steps, first step is to capture email and name, when user click submit the data is captured, and another popup appears, the new popup has a form with more fields to get more info, plus email and name field.
what I want to do is to automatically populate the email and name field from first popup and hide them with display:none so user can't see them, after submit the data is captured again (all goes to activecampaign).
the two forms works just fine, what is not working is saving the data and calling it when needed
here is the js I'm using
jQuery(function($){
// PART I: Saving user details locally
$('#arlington-field-submit').on('click', function(){
// check if the user's browser has localStorage support
if (typeof(Storage) !== "undefined") {
// Code for localStorage/sessionStorage.
// store the full name in localStorage
var fullname = document.querySelector("input[name=arlington-name]");
localStorage.user_name = fullname.value;
// save the email in localStorage
var email = document.querySelector("input[name=arlington-email]");
$("input[name=fullname]").val(localStorage.getItem("server"));
localStorage.user_email = email.value;
}
});
// PART II: Pre-filling forms forms with locally saved values
if (typeof(Storage) !== "undefined") {
// check if the user has a name field stored
if (localStorage.user_name) {
name_field = document.querySelector("._form input[name=fullname]");
name_field.value = localStorage.user_name;
}
// check if the user has an email field stored
if (localStorage.user_email) {
email_field = document.querySelector("._form input[name=email]");
email_field.value = localStorage.user_email;
}
}
});
first form html:
<div id="arlington-element-form" class="arlington-element-form arlington-element" data-element="form">
<div id="arlington-form" class="arlington-form arlington-has-name-email arlington-has-buttons">
<div class="arlington-form-wrap"><input id="arlington-field-comments" name="arlington-comments" type="text" data-selectable="true" data-target="#builder-setting-comments_value" class="arlington-field-comments" placeholder="" value="" style="" autocomplete="off"><input id="arlington-field-name" name="arlington-name" type="text" data-selectable="true" data-target="#builder-setting-name_value" class="arlington-field-name" placeholder="Enter your name here..." value="">
<input id="arlington-field-email" name="arlington-email" type="email" data-selectable="true" data-target="#builder-setting-email_value" class="arlington-field-email" placeholder="Enter your email address here..." value="" >
<input id="arlington-field-submit" name="arlington-submit" type="submit" data-selectable="true" data-target="#builder-setting-submit_value" class="arlington-field-submit" value="JOIN NOW" >
</div>
<div class="arlington-yesno-wrap">
<button id="arlington-button-yes" type="button" name="arlington-yes" data-selectable="true" data-target="#builder-setting-yes_value" data-action="form" data-type="yes" class="arlington-button-yes arlington-button-yesno">Submit!</button>
</div></div></div>
second form html:
<form method="POST" action="xxxxxx" id="_form_8_" class="_form _form_8 _inline-form _dark" novalidate> <input type="hidden" name="u" value="8" /> <input type="hidden" name="f" value="8" /> <input type="hidden" name="s" /> <input type="hidden" name="c" value="0" /> <input type="hidden" name="m" value="0" /> <input type="hidden" name="act" value="sub" /> <input type="hidden" name="v" value="2" />
<div class="_form-content">
<div class="_form_element _x72304349 _full_width "> <label class="_form-label"> Full Name </label>
<div class="_field-wrapper"> <input type="text" name="fullname" placeholder="Type your name" /> </div>
</div>
<div class="_form_element _x10201592 _full_width "> <label class="_form-label"> Email* </label>
<div class="_field-wrapper"> <input type="text" name="email" placeholder="Type your email" required/> </div>
</div>
<div class="_form_element _x29901314 _full_width "> <label class="_form-label"> Phone </label>
<div class="_field-wrapper"> <input type="text" name="phone" placeholder="Type your phone number" /> </div>
</div>
<div class="_button-wrapper _full_width"> <button id="_form_8_submit" class="_submit" type="submit"> Submit </button> </div>
<div class="_clear-element"> </div>
</div>
</form>
Since the input which is being clicked is a submit button, chances are that the page is navigating before the JS within the click handler gets a chance to fire.
Try and replace
$('#arlington-field-submit').on('click', function(){
with:
$('#_form_8_').on('submit', function(event){
Then you can prevent the form from actually submitting so your JS can run:
$('#_form_8_').on('submit', function(event){
event.preventDefault();
// Do localStorage stuff
$(this).submit(); // submit the form normally after localStorage is saved
});
The way you look for elements is wrong, because you forgot quotes wrapping attribute values:
var fullname = document.querySelector("input[name=arlington-name]");
should be:
var fullname = document.querySelector('input[name="arlington-name"]');
And so on...
BTW I'm surprised you don't report an error like "An invalid or illegal string was specified".
The section below should only appear if the user selects the "Yes" option. This section (id="co-op") is embedded inside of a long Form. All of the inputs within the section are required (using HTML5 "Required" attribute). However if the user selects "No" the section below doesn't display within the form. This means that I would like to disable the "Required" fields within the section when the user selects "No"; since they can't view the inputs. Currently they are still submitting and preventing a successful submission.
Thanks!
<section id="co-app">
<div class="container">
<div class="row">
<div class="col-md-3">
<div class="form-group">
<label for="fullName">Co-Applican'ts Information</label>
<input type="text" class="form-control" name="firstName" placeholder="First Name" required>
</div><!--/form-gp-->
</div><!--/col-md-4-->
<div class="col-md-1">
<div class="form-group">
<input type="text" class="form-control" name="middleName" placeholder="M.I." maxlength="1" id="middle-name" required>
</div><!--/form-gp-->
</div><!--/col-md-1-->
<div class="col-md-3">
<div class="form-group">
<input type="text" class="form-control" id="last-name" placeholder="Last Name" required>
</div><!--/form-gp-->
</div><!--/col-md-1-->
</div><!--/row-->
</div><!--/container-->
</section><!--/co-app-->
Using the jquery validation engine plugin I was able to use the following jquery to toggle the hidden elements when selected and remove the "required" attribute when not selected.
$(document).ready(function() {
$("#retired-select-coapp, #retired-select-primary ").change(handleNewSelection);
// Run the event handler once now to ensure everything is as it should be
handleNewSelection.apply($("#retired-select-coapp, #retired-select-primary"));
/** Step One Co-App Info **/
$('#co-app').hide();
$(".app-choice").change(function () { //use change event
if (this.value == "option2") {
$('#co-app').stop(true,true).slideDown('1000'); //than show
$('#co-app input,#co-app select').addClass('validate[required]');
} else {
$('#co-app').stop(true,true).slideUp('1000'); //else hide
$('#co-app input, #co-app select').removeClass('validate[required]');
}
});