In a form (named createform) many inputs are created dynamically by clicking on add button (from 0 to any number for each kind of input).
The problem I'm having is the validation of the inputs that were created dynamically, because there is a complex logic behind it.
THE SCENARIO
I can have several different inputs:
brand
model
country
region
The first of them is called brand1, model1, country1 and region1, then adding others they will be called for instance brand2... brand50
In the starting scenario there will be only brand1 and model1. The country and region inputs are added only by clicking on a button.
THE VALIDATION CONDITION
I have to submit the form only in two cases:
If there is at least one brand + one model where both of them are not empty (any brand and any model, so it can also be brand5 and model12)
If there is at least one brand + country + region not empty (all of them not empty, same logic than before)
I made the following validation function which works good if I assume that I just have the first brand,model,country and region (so brand1,model1,country1 and region1).
THE CODE
function validateForm() {
var brand = document.forms["createform"]["brand1"].value;
var model = document.forms["createform"]["model1"].value;
if (document.forms["createform"]["country1"] === undefined) {
var country = "";
} else {
var country = document.forms["createform"]["country1"].value;
}
if (document.forms["createform"]["country1"] === undefined) {
var region = "";
} else {
var region = document.forms["createform"]["region1"].value;
}
if ((brand != "") && (model != "")) {
alert("Send");
return true;
} else if ((brand != "") && (country != "") && (region != "")) {
alert("Send");
return true;
} else {
alert("Impossible to send");
return false;
}
}
For better reading of the code I added return true even if it is not necessary.
The main problem is that it is impossible to know how many inputs there will be of every different kind. I was thinking about trying by checking if the inputs are starting with brand,model,country or region but I don't know how to cross my controls in my validation function with all the possible results.
Do you guys have any idea of how to solve this?
What you need is a way to access all your brand and model elements by the start of their name.
var elements = document.querySelectorAll("form[id='createform']>input[id^='brand']");
This will give you an array (instead of your single valued variable) which you can loop through looking for your values.
The nifty querySelectorAll accepts selectors which can narrow your search to all matching elements. In the example, it gets all input elements within a form named "createform" which start with (^=) "brand".
var brandelements = document.querySelectorAll("#createform select[name^='brand'] option:checked:not([value=''])");
This is the best way to get all the values of a select (you can easily change with a normal input) that are not empty.
Related
Hopefully you all don't get pissed at me for such a seemingly simple question..
Basically, I have a PDF form that I'm scripting with javascript.
I have a bunch of check boxes that I would like to set required and/or not required based on other inputs and I'm trying to repeat code as little as possible, especially since there's a ton of inputs.
Right now, the best way I can accomplish what I'm attempting is by setting a function for each instance of inputs as follows:
function setWalkwayNotRequired() {
this.getField("sidewalkAsphalt").required = false;
this.getField("sidewalkConcrete").required = false;
this.getField("sidewalkPavers").required = false;
this.getField("sidewalkCondition").required = false;
}
I would then call this function based on the input of a certain checkbox:
if (this.getField("sidewalkNone").value == "Yes") {
setSidewalkNotRequired();
}
Then all of the above-mentioned fields would be set to not required.
I feel like there should be a way to create a single "setRequired" or "setNotRequired" function to take a parameter of the field in question.
In my mind that would look something like this:
function setRequired(a, b, c, d) {
this.getField(a).required = true;
this.getField(b).required = true;
this.getField(c).required = true;
this.getField(d).required = true;
}
I would then call on that function for all instances, for example, walkways (like that above) or driveways, etc. like so:
if (this.getField("sidewalkNone").value == "Off") {
setRequired('"sidewalkAsphalt"', '"sidewalkConcrete"', '"sidewalkPavers"', '"sidewalkCondition"');
}
Again, in my mind what would then be output based on the above code once the function is called is something like:
if (this.getField("sidewalkNone").value == "Off") {
this.getField("sidewalkAsphalt").required = true;
this.getField("sidewalkConcrete").required = true;
this.getField("sidewalkPavers").required = true;
this.getField("sidewalkCondition").required = true;
}
Doing it the way I did in the first code block would require me to create separate functions for each set of checkboxes, creating a lot of code in an already huge file. The second way would allow me to use 1 function over and over throwing the field names as parameters depending on where I'm at in the PDF.
I'm also not very clear on if it's even legal to declare the parameters as I did with the '"..."' quotes; I did that because I need the double quotes inside the this.getField().
Again, I'm sorry if this is novice, I've just been trying to play with the code for a while now and can't get it to work.
Any input would be amazing.
You could just pass in an Array of field names:
function setRequired( fieldNames, isRequired = true ) {
for( var i = 0; i < fieldNames.length; i++ ) {
var fieldName = fieldNames[i];
this.getField( fieldName ).required = isRequired;
}
}
Usage:
if( this.getField("sidewalkNone").value == "Off" ) {
setRequired( [ "sidewalkAsphalt", "sidewalkConcrete", "sidewalkPavers", "sidewalkCondition" ] );
}
If you use hierarchical naming with dot notation, you can set properties on the parent to affect all children. For example, if you name the fields "sidewalk.Asphalt", "sidewalk.Concrete", and "sidewalk.Pavers"...
this.getField("sidewalk").required = true;
... will set all the children to be required.
I'm really trying to avoid nesting in this code snippet...
deal_trade_in_model_1 = document.getElementById('deal_trade_in_model_1').value;
deal_trade_in_amount_1 = document.getElementById('deal_trade_in_amount_1').value;
if (typeof deal_trade_in_model_1 !== 'undefined' && deal_trade_in_model_1 !== null) {
console.log(deal_trade_in_amount_1);
console.log(deal_trade_in_model_1);
if (deal_trade_in_model_1 !== null || deal_trade_in_model_1 !== "") {
if (deal_trade_in_amount_1 == null || deal_trade_in_amount_1 == "") {
console.log('entered into function');
document.getElementById("deal_trade_in_model_1").value = "";
document.getElementById("deal_trade_in_amount_1").value = "";
}
}
}
Basically, what this function does is take the value of two fields... things to know about them and what I want to do to them:
1) They're NOT required
2) If one of them is filled out, the other must be
3) If ONLY one of them is filled out, the user clicks submit, and this part of the function is called upon, I want to delete the value of both of them.
I've tried doing a compound of
&& (and)
and
|| (or)
buttttt it odiously it didn't work.
Primary question: What's the best way to get rid of the nesting (I planned on doing this twice and just swapping the code) that will be the most efficient? This, I want, to be done preferably in the smallest amount of IF statements possible.
Please note: If you change the code a lot, I might not know what you're talking about.. please be prepared to teach me or help me learn!
It sounds like you only want to do something if either of the fields are empty, but not both. Assuming both of the elements are text fields, .value will always return a string. Converting a string to boolean results in false if the string is empty, otherwise true.
So
Boolean(deal_trade_in_model_1) === Boolean(deal_trade_in_amount_1)
will be true if either both fields have a value (both will convert to true) or both fields are empty (both convert to false).
Thus your code can be reduced to
var model_1 = document.getElementById('deal_trade_in_model_1');
var amount_1 = document.getElementById('deal_trade_in_amount_1');
if (Boolean(model_1.value) !== Boolean(amount_1.value)) {
model_1.value = "";
amount_1.value = "";
}
This is really weird. I am doing validation in a js library. I check if fields are blank or null and throw an error if they are.
I have a date field that I want to check. If I do not put in a default value, the code works fine. It says the date is blank and then when I put in a value it lets it pass. But if I put in a default of #Now or #Today, it will not pick up the error if the user happened to erase the date. I know it is not really necessary - I could put a required validator on, but it is driving me crazy that I cannot figure this out.
//This SSJS script library consolidates all the validation in one place
//The postValidationError() function flags a control as invalid and provides an error message
//so that the XPages ErrorMessage control is used to display the error on the page.
var validateForm = function(){
var valid = true;
var control;
var val;
// *** REPEAT THE FOLLOWING BLOCK OF CODE FOR EACH CONTROL FOR BASIC "REQUIRED" VALIDATION
// For each field, change the Control Name in getComponent() and the error message text in postValidationError()
// Optionally, modify the IF conditions with more complex JavaScript for value ranges, regular expressions, data lookups, etc.
//Validate Location
control = getComponent("loc");
val = control.getValue();
if (isEmpty(val)) {
valid = false;
postValidationError(control,"Please enter a Loc");
}
//Validate Work Category
control = getComponent("workCategory");
val = control.getValue();
if (isEmpty(val)) {
valid = false;
postValidationError(control,"Please enter a Work Category");
}
//Validate Work Sub Category
control = getComponent("workSubCategory");
val = control.getValue();
if (isEmpty(val)) {
valid = false;
postValidationError(control,"Please enter a Sub Work Category");
}
//Validate Date
control = getComponent("date");
val = control.getValue();
if (isEmpty(val)) {
valid = false;
postValidationError(control,"Please enter a date");
}
//Validate Time Spent
control = getComponent("timeSpent");
val = control.getValue();
if (isEmpty(val)) {
valid = false;
postValidationError(control,"Please enter Time Spent");
}
// *** ---------------------------------------------------------------- ***
return valid;
}
function postValidationError(control, msg) {
if ((typeof msg) != "string")
return;
var msgObj = new javax.faces.application.FacesMessage(javax.faces.application.FacesMessage.SEVERITY_ERROR, msg, msg);
facesContext.addMessage(control.getClientId(facesContext), msgObj);
control.setValid(false);
}
function isEmpty(o){
return (o == null || o == "") ? true: false;
//return (o == null || #Trim($A(o)[0]) == "" ) ? true : false;
}
function $A( object ){
try {
if( typeof object === 'undefined' || object === null ){ return []; }
if( typeof object === 'string' ){ return [ object ]; }
if( typeof object.toArray !== 'undefined' ){return object.toArray();}
if( object.constructor === Array ){ return object; }
return [ object ];
} catch( e ) { }
}
Bryan, the recommended way in XPages for validation is to use a validator, You write much less code, you can selectively control when to validate fields, you can separate different checks from each other.
Check my thoughts about validation. In a nutshell:
Validation in code (a button, the submit event etc.) is a typical way validation is done. Being the prevalent way doesn't make it right . You need to roll your own notification mechanism (like updating a label) and tend to tie your validation into the UI. Also when you remove a field the validation routine is likely to break. Last not least: you have a hard time documenting what gets validated and why. (You see where I'm going with that)
Validators are defined together with a field and open a series of possibilities. XPages offers 9 different validators.
You can write JavaScript, regular expressions, check for data types or roll your very own. All you can do in a button/event code you can do in a validator. Since the validators themselves don't interact with the UI the designer can decide how to surface the messages without changes to the validation code. When you remove a field all its validation code goes with it, so maintenance gets much easier. Last not least: you can run an XSLT report against your XPages source and render a report that shows a field with all the defined validators, which makes documentation easier.
Form Validation are the #Formulas defined in your classic Notes form. They only fire when you have specified "Run form validation" as "On Save" or "Both". Typically you would use those when upgrading existing applications.
Extracted from another blog entry
I have to use unescape() function in an if-else statement. In my website I have two pages, one with a form that the user fills and the second page have to get the information from the filled form by unescape function. I need the if-else statement because in the form I put two radio buttons that each one adds different text areas with different ids' and names so I want to check in the second page what text fields are are filled. (all the fields created by clicking on a radio button which starts a javascript function so in the next page I must check if the field was created and not just to check if it is an unfilled text field).
It is a little bit hard for me to explain so just check the code. In the code you will see params["placeName"] and so on, so placeName for example like all the others is a text field name from the previous page.
So the question is - what does unescape function returns if the component name I insert as a paramater does exist in the previous page?
<script type="text/javascript">
function getParams() {
var idx = document.URL.indexOf('?');
var params = new Array();
if (idx != -1) {
var pairs = document.URL.substring(idx + 1, document.URL.length).split('&');
for (var i = 0; i < pairs.length; i++) {
nameVal = pairs[i].split('=');
params[nameVal[0]] = nameVal[1];
}
}
return params;
}
params = getParams();
//from here it is what I want to do (I don't know if this condition in the if statement is correct, this is what I ask)
// if (unescape(params["placeName"]) == false) {
// }
// else {
var place = unescape(params["placeName"]);
var country = unescape(params["country"]);
var city = unescape(params["city"]);
var address = unescape(params["address"]);
var type = unescape(params["type"]);
var rate = unescape(params["rate"]);
// }
</script>
It can also work if I could check what radio button is checked
You are asking what will unescape(params["something"]) return if params["something"] is not present. The answer is undefined. So you need to check equivalence to "undefined". Meaning: if (unescape(params["placeName"]) == "undefined") (in this case params["placeName"] is not present (was not created).
The undecode function returns -as it's name indicated- a decoded string. If you enter a value that's not defined it will probably cause an error because of the indefinition. If what you want is to check whether the element was or not created or not you could use
if (params.placeName !== undefined) {
// It was created
}
instead.
Aditionally, if you want to check which radio button was checked use
if (document.getElementById('foo').checked) {
// Radio button with id 'foo' was checked
} else if (document.getElementById('bar').checked) {
// Radio button with id 'bar' was checked
} else if
...
I'm having a pretty simple issue I think but I cannot get it solved.
On form submit I want to compare the values of two hidden input types and if any match is found return an alert to the user and prevent submit. Pretty much the hidden input type values will be 1-3, could be 1, 12, 123, 13 etc. So if 1 and 123, throw an alert.
So I've tried something like this, but I'm obviously confused about what I'm doing hehe.
var new_products = $('#new_products');
var array_new_products = jQuery.makeArray(new_products);
var existing_products = $('#existing_products');
var array_existing_products = jQuery.makeArray(existing_products);
$("#my_form").submit(function(e) {
if (jQuery.inArray(existing_products, new_products) >= 0) {
e.preventDefault();
alert ("This Promotion matches one or more products already associated to this Group. If you continue the existing Promotion will be cancelled and replaced with the currently selected Promotion!");
}
return true;
});
I'm open to doing this by comparing strings and returning matches or anything really. I'm just pretty new to Jquery. Thanks in advance.
$.each($('#new_products').val().split(''), function(i, char) {
var existing = $('#existing_products').val();
if (existing.indexOf(char) != -1)
alert('mathces found');
});
checks if any of the characters in the returned value from #new_product exists in the value returned from #existing_products ?