I have a form that submits using jquery, everythinh works fine. If the there is an error the browser displays the error. But the problem is if the form is resubmitted the error wont change. Either to nothing or a different message.
<script>
$(document).ready(function(e) {
$('#addNew').submit(function(e) {
event.preventDefault();
var err_count = 0;
var name_err = '';
var name_err_count = 0;
if($('#f_name').val() === ''){
err_count++;
name_err_count++;
name_err = "You need a first name";
}else{
name_err = '';
}
if($('#l_name').val() === ''){
err_count++;
name_err_count++;
if(name_err_count > 0){
name_err += " and a last name.";
}else{
name_err += "You need a last name";
}
}else{
name_err = '';
}
$('#name_err').replaceWith(name_err);
});
});
</script>
<select id="prefix"><option>Mr</option><option>Mrs</option><option>Miss</option><option>Ms</option></select> <input type="text" id="f_name" name="f_name" placeholder="First Name" /> <input type="text" id="l_name" name="l_name" placeholder="Family Name" /><br />
<div class="form_err" id="name_err"></div>
There are 4 problems with your code, let's tackle them in order of appearance:
You passed the event as variable e to your submit-function, so variable event is undefined:
$('#addNew').submit(function(e) {
event.preventDefault();
undefined.preventDefault(); is obviously going to crash your function upon execution (so that's why it 'does not work': everything after that statement is not executed).
Fix:
$('#addNew').submit(function(event) { // or just `e` instead of `event`
event.preventDefault(); // or just `e` instead of `event`
Then you have:
err_count++;
name_err_count++;
if(name_err_count > 0){
name_err_count will be always be > 0 since you have just (post-)incremented it..
Solution: increment your error-counter(s) after your check:
if (name_err_count > 0) { //you could omit the `> 0` check and inverse if/else
// logic here
} else {
// logic here
}
err_count++;
name_err_count++;
Next, you end with an else on your Last Name if-check:
}else{
name_err = '';
}
Thus, if the value of element#l_name is set (so not '') your name_err string will be cleared to '', even if it held an error-message generated by your previous first name check..
Fix: delete it (since your name_err was already an empty string upon initialization and not filled by other error-messages if none of them apply).
Also have a look at If vs. else if vs. else statements?
Finally, by using $('#name_err').replaceWith(name_err); you replace the element #name_err with an un-identified textnode (containing your error-message). When the function runs the next time, there is no #name_err element to replace.
To fix this you should use elm.html() (or less preferably elm.text())
Also have a look at this answer: What's the difference between jQuery's replaceWith() and html()?
So (applying above fixes) here is your corrected code (jsfiddle here):
$(document).ready(function (e) {
$('#addNew').submit(function (event) {
event.preventDefault();
var err_count = 0;
var name_err = '';
var name_err_count = 0;
if ($('#f_name').val() === '') {
name_err = 'You need a first name';
err_count++;
name_err_count++;
}
if ($('#l_name').val() === '') {
if (name_err_count > 0) {
name_err += ' and a last name.';
} else {
name_err += 'You need a last name';
}
err_count++;
name_err_count++;
}
$('#name_err').html(name_err);
});
});
PS, you could delete the name_error_count and just check if your name_err evaluates to TRUE or FALSE (empty strings evaluate to FALSE in javascript) in conjunction with a ternary (and some more optimizations) for simpler/easier to read code.
$(document).ready(function(e) {
$('#addNew').submit(function(event) {
var err_count = 0,
name_err = '';
event.preventDefault();
if ($('#f_name').val() === '') {
name_err = 'a first name';
err_count++;
}
if ($('#l_name').val() === '') {
name_err += (name_err ? ' and ' : '')
+ 'a last name';
err_count++;
}
// example of simply adding a check (for a hobby)
// if ($('#hobby').val() === '') {
// name_err += (name_err ? ' and ' : '')
// + 'a hobby';
// err_count++;
// }
$('#name_err').html( name_err ? 'You need ' + name_err : '' );
});
});
Example jsfiddle here.
Another approach would be to use an array to hold your partial error-messages (that were added to it using arr.push()). That way you can keep track/count of the error's (per section if you'd wanted, like name) by using arr.length and convert them to a string using arr.join(' and ') even whilst outputting your string: (arr.length ? 'You need ' + arr.join(' and ') : '')
Note: this way you could also simply obtain you total number of errors by doing err_count+=arr_section_err.length; after each check-block. In other words, err_count++; in every check could then also be deleted.
That would look like this:
$(document).ready(function(e) {
$('#addNew').submit(function(event) {
var err_count = 0,
name_err = [];
event.preventDefault();
if($('#f_name').val() === '') name_err.push('a first name');
if($('#l_name').val() === '') name_err.push('a last name');
// if($('#hobby').val() === '') name_err.push('a hobby'); // TRIVIAL
err_count+=name_err.length;
$('#name_err').html( name_err.length
? 'You need ' + name_err.join(' and ')
: ''
);
});
});
Example jsfiddle here.
As I have just explained that an empty string is falsy in javascript, then
if($('#f_name').val() === '') name_err.push('a first name');
equals
if(!($('#f_name').val())) name_err.push('a first name');
which equals
$('#f_name').val() || name_err.push('a first name');
$('#l_name').val() || name_err.push('a last name'); // showcasing the beauty
$('#hobby').val() || name_err.push('a hobby'); // note alignment on ||
Example jsfiddle here. Pretty elegant and simple if you ask me.
As you see, you could continue to build your error-message dynamically as you originally intended (contrary to using if/else structures that (repeatedly) check (combinations of) element-values and having complete static strings for every combination (as someone else suggested) resulting in an exponential increase in 'work' (check's and DOM-access) and a rather unmaintainable 'spaghetti'-code when checking for example just 5 elements..).
Hope this helps!
Actually, this should be an else if.
$(document).ready(function (e) {
$('#addNew').submit(function (e) {
e.preventDefault();
if($('#f_name').val() === '' && $('#l_name').val() === ''){
name_err = " You need a first and a last name.";
}else if($('#l_name').val() === '' && $('#f_name').val() !== ''){
name_err = "You need a last name";
}else if($('#l_name').val() !== '' && $('#f_name').val() === ''){
name_err = "You need a first name";
}else{
name_err = 'Looks Good';
}
$('#name_err').html(name_err);
});
});
…now with rock solid else if.
http://jsfiddle.net/VS3Ya/2/
Try this,
<script>
var err_count ;
var name_err;
var name_err_count;
$(document).ready(function(e) {
$('#addNew').submit(function(e) {
event.preventDefault();
initializeVariables();
if($('#f_name').val() === ''){
err_count++;
name_err_count++;
name_err = "You need a first name";
}
else{
name_err = '';
}
if($('#l_name').val() === ''){
err_count++;
name_err_count++;
if(name_err_count > 0){
name_err += " and a last name.";
}
else{
name_err += "You need a last name";
}
}
else{
name_err = '';
}
$('#name_err').replaceWith(name_err);
});
});
function initializeVariables(){
err_count = 0;
name_err = '';
name_err_count = 0;
}
</script>
I think the problem is that the variables are still holding onto the values. I am not sure about the .html() or .replaceWith(), but going by the discussion, .html() seems to be the way.
Related
I have a form myForm and I want to check if specific input field are filled out before sending the form. I'm very new to JavaScript so I don't really know what I did wrong. Any help is welcomed.
function validateForm() {
var validate = true;
var alert_string = "";
var children = $("#myForm").children("input");
console.log(children.size());
for(var i = 0; i < children.length ; i++){
if(children[i].attr(id).substring(0,8) != "ABC_FLAT"){
if(children[i].attr(id) == null || children[i].attr(id) == ""){
validate = false;
alert_string = alert_string.concat(childrern[i].attr(id)).concat(", ");
}
}
}
alert_string = alert_string.concat("must be filled out !");
if(validate == false){
alert(alert_string);
return false;
}
return true;
}
children[i].attr(id) == "" // wrong
You don't have to check whether their ids are null, you have to check whether their values are empty :)
if(children[i].value == "")
Since you are already using jQuery, you can simplify that code to a great extent. For example a simple "all fields filled" check can be
var flag=0;
$('#myForm').each(function() {
if ( $(this).val() === '' )
flag=1;
});
if you'll use jQuery, you can check the input fields if empty AND trap also white space/s. Add a class to all input fields , e.g. class="required" and add attribute fieldname with respective value for each input field.
var requiredFields = "";
$("#myForm").find('.required').each(function () {
if ($(this).val().trim().length == 0) {
requiredFields += " - " + $(this).attr("fieldname") + "\n";
}
});
if (requiredFields != "") {
alert("Please enter the following required field(s): \n" + requiredFields);
} else {
//save here
}
You can use required like <input required type="text" name="email" id="log" /> or use jQuery like
$("form").submit(function() {
var has_empty = false;
$(this).find('input').each(function() {
if(! $(this).val()) {
has_empty = true;
return false;
}
});
if(has_empty){return false;}
});
I have some input filed into a form. I am trying to check the empty and null of those value.
My js code as:
$(function(){
$('#submit').click(function(){
var cid = $('#CTID').val();
var sid = $('#sbj').val();
var d = $('#bdate').val();
var t = $('#time').val();
var dt = d+' '+t;
var path = '/admin/exam_schedule';
if (cid ==''||cid==null || sid==''||cid==null || d==''||d==null || t==''||t==null) {
alert('Input all data fields');
}
else{
var url='/admin/insert_exam_schedule';
$.post(url,{c:cid,s:sid,d:dt},function(data){
alert(data);
window.location.href= path
});
}
});
});
But the problem of this code are: When I give space into the input field then it takes the space as input.But, I want to validate all of the possible way, so that I can take real data as input.
val() will only return null for a select element, everything else should return '', therefore, if you aren't using a select element then str != '' or str.length > 0 should be sufficient.
If you are using a select element then you check whethre the value is assigned first e.g. str && str != '' or str && str.length > 0 (or alternatively you default null to '' for consistency).
If you want to exclude whitespace-only strings then use trim() during validation.
var cid = $('#CTID').val();
var sid = $('#sbj').val();
var d = $('#bdate').val();
var t = $('#time').val();
var dt = d+' '+t;
if (cid.trim() == '' || sid.trim() == '' || d.trim() == '' || t.trim() == '') {
// data invalid
}
else {
// data valid
}
Try,
var condition = $('#CTID,#sbj,#bdate,#time').map(function(){
return $.trim(this.value);
}).get().join('') === '';
if(condition){ alert('Input all data fields'); }
DEMO
Improvised version,
var condition = false;
$('#CTID,#sbj,#bdate,#time').each(function(){
if($.trim(this.value) === "") {
condition = true;
return false;
}
})
if(condition){ alert('Input all data fields'); }
Full code would be,
$('#submit').click(function(e){
e.preventDefalut();
var condition = $('#CTID,#sbj,#bdate,#time').map(function(){
return $.trim(this.value);
}).get().join('') === '';
if(condition){ alert('Input all data fields'); }
else {
var url='/admin/insert_exam_schedule';
$.post(url,{c:cid,s:sid,d:dt},function(data){
alert(data);
window.location.href= path
});
}
});
The below works, how would i go about including a 2nd "txtArea2"? I've tried joining a & (document.getElementById("txtArea2").value == '') but doesnt work. I'm new to js syntax if someone could help.
if(document.getElementById("txtArea1").value == '')
{
alert("debug");
document.getElementById("txtArea1").style.display ="none";
return false;
};
I'm not sure if I understand your question correctly but you probably want to compare them with || (OR) operator, so if txtArea1 or txtArea2 is empty then the validation shall not pass. That means both textareas will be required fields.
if (document.getElementById("txtArea1").value == '' || document.getElementById("txtArea2").value == '')
{
alert("debug");
document.getElementById("txtArea1").style.display ="none";
return false;
};
Double && specifies the AND condition.
if (document.getElementById("txtArea1").value == '' && document.getElementById("txtArea2").value == '')
If you want to treat both separately, you'll have to use two separate if statements as well. (I outsourced the textareas into variables for readability)
var txtarea1 = document.getElementById("txtArea1");
var txtarea2 = document.getElementById("txtArea2");
if(txtarea1.value == '')
{
alert("debug");
txtarea1.style.display = "none";
return false;
};
if(txtarea2.value == '')
{
alert("debug");
txtarea2.style.display = "none";
return false;
};
If you want to do one thing if either of them (1 or 2) is empty, try this:
if(txtarea1.value == '' || txtarea2.value == '')
{
alert("debug");
txtarea1.style.display ="none";
txtarea2.style.display ="none";
return false;
};
var t1 = document.getElementById("txtArea1").value;
var t2 = document.getElementById("txtArea2").value;
if( t1 == '' || t2 == '')
{
alert("debug");
document.getElementById("txtArea1").style.display ="none";
return false;
};
I am trying to do a Javascript form validation, and I want to set the formValue to 0 in several cases. That is, if ANY of the required fields are not filled out, the value should go to 0.
function formValidation() {
var formValue = 1;
if (document.getElementById('orgname').value == '') formValue = 0;
else if (document.getElementById('culture[]').value == '') formValue = 0;
else if (document.getElementById('category[]').value == '') formValue = 0;
else if (document.getElementById('service[]').value == '') formValue = 0;
if (formOkay == 1) {
return true;
} else if (formOkay == 0) {
alert('Please fill out all required fields');
return false;
}
}
Is there a more elegant way to do this?
EDIT: Script does not appear to be working, now.
You can do some looping:
var toCheck = ['orgname', 'culture[]', 'category[]', 'category[]']
for(var id in toCheck )
{
if(document.getElementById(id).value == ''){
formValue = 0;
break;
}
}
A more elegant way can be that you specify a 'required' class on each input that you want to check and than do the following using jQuery:
$(document).ready(function(){
var toCheck = $('.required');
var formValue = 1;
$.each(toCheck, function(index, element){
if(element.val() == '')
formValue = 0;
});
});
I've done this in other languages using boolean logic, taking advantage of the & operator. It always returns false if any of the values are false.
Something like:
function formValidation() {
var formValue = true;
formValue &= document.getElementById('orgname').value != '';
formValue &= document.getElementById('culture[]').value != '';
formValue &= document.getElementById('category[]').value != '';
formValue &= document.getElementById('service[]').value != '';
if(!formValue) {
alert('Please fill out all required fields');
}
return formValue;
}
This has the advantage of working for other scenarios where your logic is more complicated. Anything that evaluates in the end to true/false will fit right in with this solution.
Then I'd work on reducing logic duplication:
function formValidation() {
var formValue = true;
var elementIdsToCheck = ['orgname', 'culture[]', 'category[]', 'category[]'];
for(var elementId in elementIdsToCheck) {
formValue &= document.getElementById(elementId).value != '';
}
if(!formValue) {
alert('Please fill out all required fields');
}
return formValue;
}
Something like this should help (this assumes that value attribute is available on the referenced elements):
var ids = ["orgname", "culture[]", "category[]", "service[]"],
formValue = 1; // default to validation passing
for (var i = 0, len = ids.length; i < len; i++) {
if (document.getElementById(ids[i]).value === "") {
formValue = 0;
break; // At least one value is not specified so we don't need to continue loop
}
}
Building upon #Baszz's second answer using jQuery, you could also build a more generic solution using HTML5 data- attributes:
$(function() {
$('form').submit(function() {
var toValidate = $(this).find('input[data-validation]');
for(var i=0; i<toValidate.length; i++) {
var field = $(toValidate[i]);
if(field.val().search(new RegExp(field.data('validation'))) < 0) {
alert("Please fill out all required fields!");
return false;
}
}
});
});
You can then specify regular expressions in your markup:
<form>
<input type="text" data-validation=".+" />
</form>
For required fields you can use ".+" as a regular expression, meaning the user has to enter at least one character, but you can of course use the full potential of regular expressions to check for valid email addresses, phone numbers or zip codes etc...
I keep getting the following error when I try to insert values by clicking the Next button on values that are already entered in.
Unable to get the value of the property '0': object is null or undefined.
I believe the error is happening at the last value in the array. I indicated the line below with a comment in the code. I want it to get the next value in the array but there isn't one created yet (it gets the next value just fine if the next value is not the last one in the array).
I think that is the reason it's throwing an object null. However, I can't seem to check for the null/undefined and set it using statements such as result[count+1][0] == undefined because it doesn't work! It always throws an error no matter what I do.
Some help would be much appreciated.
Test case:
Insert a value in text box 1 and text box 2
Click Next
Click Previous (in order to edit the values inserted above)
Change the values in the text boxes to something else
Click Next -- error happens
Code:
<html>
<head>
<script type="text/javascript"></script>
</head>
<body>
<script type="text/javascript">
var result = new Array();
var count = 0;
var input1 = new Array();
var input2 = new Array();
function move(direction) {
if(direction == 'next')
{
var rate1 = [document.getElementById("txt1").value];
var rate2 = [document.getElementById("txt2").value];
if (result.length == count){
if (rate1 == '' || rate2 == '') {
alert('you need to put in a value');
}
else {
result.push([[rate1], [rate2]]);
document.getElementById("txt1").value = '';
document.getElementById("txt2").value = '';
count++;
}
}
else {
try{
(result[count][0]) = document.getElementById("txt1").value;
(result[count][1]) = document.getElementById("txt2").value;
document.getElementById("txt1").value = result[count++][0]; //error happening here. trying to show next value but there isn't one created yet.
document.getElementById("txt2").value = result[count++][1];
document.getElementById("txt1").value = '';
document.getElementById("txt2").value = '';
}
catch(err) {
alert(err.description);
}
count++;
}
}
if (direction == 'prev')
{
if(count <= 0)
{
alert("no more elements");
}
else
{
var prev_val1 = (result[count - 1][0]);
document.getElementById("txt1").value = prev_val1;
var prev_val2 = (result[count - 1][1]);
document.getElementById("txt2").value = prev_val2;
count--;
}
}
document.getElementById("txtresult").value = result;
}
</script>
<li>text 1</li>
<input type="text" id="txt1"/>
<br>
<li>text 2</li>
<input type="text" id="txt2"/>
<br>
<input type="button" id="btn" value="next" onclick="move('next')" />
<input type="button" id="btnprevious" value="previous" onclick="move('prev')" />
<br>
<input type="text" id="txtresult"/>
</body>
</html>
You can add a check like this:
if (typeof result[count++] === "undefined") { /* do or do not */ };
Right before:
document.getElementById("txt1").value = result[count++][0];
function move(direction) {
if(direction == 'next')
{
var rate1 = [document.getElementById("txt1").value];
var rate2 = [document.getElementById("txt2").value];
if (result.length == count){
if (rate1 == '' || rate2 == '') {
alert('you need to put in a value');
}
else {
result.push([[rate1], [rate2]]);
document.getElementById("txt1").value = '';
document.getElementById("txt2").value = '';
count++;
}
}
else {
try{
(result[count][0]) = document.getElementById("txt1").value;
(result[count][1]) = document.getElementById("txt2").value;
if( result[ ++count ] ) // this checks for undefined
{
document.getElementById("txt1").value = result[count][0]; //error happening here. trying to show next value but there isn't one created yet.
document.getElementById("txt2").value = result[count][1];
}
else
{
document.getElementById("txt1").value = '';
document.getElementById("txt2").value = '';
count--; // decrement counter
}
}catch(err) {
alert(err.description);
}
count++;
}
}
if (direction == 'prev')
{
if(count <= 0)
{
alert("no more elements");
}
else
{
var prev_val1 = (result[count - 1][0]);
document.getElementById("txt1").value = prev_val1;
var prev_val2 = (result[count - 1][1]);
document.getElementById("txt2").value = prev_val2;
count--;
}
}
document.getElementById("txtresult").value = result;
}
why do you do count++ in these 2 lines?
document.getElementById("txt1").value = result[count++][0]; //error happening here. trying to show next value but there isn't one created yet.
document.getElementById("txt2").value = result[count++][1];
seems like interpreter first increment the count and then try to get item of result which is undefined...
as i undestand pressing previous must "set cursor" to previous vaues so you can change previously entered values... in this case you shouldn't increment counter in these lines.. just remove ++
I don't get why you embedded the arrays three deep. I cleaned up some of the code and made the names more understandable (at least to me).
Regardless, when you were on the last value in the array, count++ didn't exist. Also, don't use count++ as this will increment your count var. Don't use ++ to simplify unless you truly know what you're doing and want to increment. Also, tricky shortcuts will confuse people trying to read your code, so try to be as explicit as possible. (There are exceptions to this statement, as in, you don't need to write for a person who has never coded before)
Here is working javascript:
var result = new Array();
var count = 0;
function move(direction) {
if(direction == 'next') {
var box1 = document.getElementById("txt1").value; //why did you wrap these as arrays?
var box2 = document.getElementById("txt2").value; //
if (result.length == count){
if (box1 == '' || box2 == '') {
alert('you need to put in a value');
} else {
result.push([box1, box2]); //why did you wrap individual numbers in arrays?
document.getElementById("txt1").value = '';
document.getElementById("txt2").value = '';
}
} else {
try{
result[count][0] = document.getElementById("txt1").value;
result[count][1] = document.getElementById("txt2").value;
if(result[count+1]) { // need this because if on last value in the array, count+1 will not exist yet
document.getElementById("txt1").value = result[count+1][0]; //do not do ++. this will increment count here. don't be tricky with ++
document.getElementById("txt2").value = result[count+1][1]; //because it will confuse others and lead to off by 1 errors
} else {
document.getElementById("txt1").value = '';
document.getElementById("txt2").value = '';
}
}
catch(err) {
alert(err.description);
}
}
count++;
}
if (direction == 'prev') {
if(count <= 0){
alert("no more elements");
} else {
var prev_val1 = result[count - 1][0];
var prev_val2 = result[count - 1][1];
document.getElementById("txt1").value = prev_val1;
document.getElementById("txt2").value = prev_val2;
count--;
}
}
document.getElementById("txtresult").value = result;
}