# Basic form validation

Question + Desired Outcome

The code below works currently, however I'm not convinced the utilisation of an Array to iterate through numerous non-existent form fields is anywhere near efficient enough for my liking. Can this process be improved to effectively eliminate the first step in the Suggested Solution?

Desired Outcome: When a response is submitted on FormB, validate data on FormA to ensure entries have been at least some input on each field.

Background

We're using a support ticketing system within our organisation which thus far is working pretty well. One minor niggle however is that the 'View Ticket' page separates "Important Ticket Variables" (assigned technician, ticket category etc.) - from the "Reply to Ticket" form. Two forms, one page. Validation for both forms happens post-submit on the next page, again each is separate from the other.

In theory, that method makes sense. However, as they are two separate forms, what this often means is that people are able to bypass often-critical data from the "important ticket variables", and just add a reply. An element of human-training exists here but as ever, a programmatic change will satisfy the need for consistency.

Save for rewriting the whole process to resolve this issue, I've looked at putting in a fairly simple JS "overlay" on the view ticket page, so that when they submit a "Reply to ticket" - it does a quick verification to make sure all the 'Important Ticket Variables' have some form of entry. It's a quick fix but comes with some (for me) interesting challenges.

Languages

The main application is written in PHP, using MySQL, complemented with jQuery v1.3.2.

Constant

"Important ticket variables" always have a name= of ticket_fields[customXX], where XX is basically the id in the database, which at present means we're at an upper limit of around 60 at the moment, obviously this may increase in time as more ticket_fields are created!

Not all ticket_fields are used on every ticket, some tickets use 5-10 fields, others use none.

Example FormA data (formatting stripped out)

<input type="radio" name="ticket_fields[custom5][selection]" id="custom50" value="3"  />&nbsp;<label for="custom50">No</label>&nbsp;
<input type="radio" name="ticket_fields[custom5][selection]" id="custom51" value="4"  />&nbsp;<label for="custom51">Yes</label>&nbsp;

<input type="checkbox" name="ticket_fields[custom6][selections][]" id="custom60" value="1"  />&nbsp;<label for="custom60">A</label>
<input type="checkbox" name="ticket_fields[custom6][selections][]" id="custom64" value="5"  />&nbsp;<label for="custom64">B</label>&nbsp;

<select name="ticket_fields[custom27][parent]" id="ticket_fields_custom27_parent"  >
<option value="129562786078">Sample Option - Add new option, then delete this</option>
<option value="129562792948">Top level</option>
</select>


Suggested Solution

This JS executes onSubmit of FormB:

  // ####################################################################
// The following bits validate the 'Additional Ticket Fields' on submit
// ####################################################################
// Need an array of numbers for some horrible hacking. Used to iterate through the dynamically generated "ticket_fields" 100 should be safe, famous last words.
var numArray = new Array();
var b;
for (b = 0; b < 100; b++) { numArray[b] = b; }

// Text boxes

// iterates through existing ticket_fields and finds existing radio buttons, then validates on that radio button
$.each(numArray, function(i, v) { var radbut =$('input:radio[name^="ticket_fields[custom' + v + ']"]');
// If found a checkbox, validate it
if (radbut.length > 0) {
var radbut2 = $('input:radio[name^="ticket_fields[custom' + v + ']"]:checked'); console.log(radbut2.length); if (radbut2.length > 0) { } else { validationFail = true; } } else { // do nowt } }); // Check boxes // iterates through existing ticket_fields and finds existing checkboxes, then validates on that checkbox$.each(numArray, function(i, v) {
var chkbox = $('input:checkbox[name^="ticket_fields[custom' + v + ']"]'); // If found a checkbox, validate it if (chkbox.length > 0) { var chkbox2 =$('input:checkbox[name^="ticket_fields[custom' + v + ']"]:checked');
if (chkbox2.length > 0) {  } else { validationFail = true; }
} else {
// do nowt
}
});

// Select boxes ... includes multi-levels
// Checks each select box in turn, fails if value set to 0. Does nothing if no selectors exist.
$('select[name^="ticket_fields"] option:selected').each(function(){ if (this.length) { } else { if(this.value == 0) { validationFail = true; } } }); if (validationFail) { alert('Please ensure all Additional Ticket Fields are completed. \n REMEMBER: Click Update when done.'); return false; }  ## 2 Answers I managed to get around a generic array by pulling out the numbers from the name= attribute on each form field with the following: // Pulls numbers from submitted "ticket_fields" which are stored in the name= attribute. // Used to iterate through the dynamically generated "ticket_fields" var numArray = new Array();$(':input[name^="ticket_fields"]').each(function(){
fieldId = $(this).attr('name').replace(/\D/g, ""); if ($.inArray(fieldId,numArray) > -1) { } else { numArray.push(fieldId); }
});


This makes it much friendlier, so rather than numArray having a ridiculous level of integers to iterate through, it gets exactly the right values from the form fields themselves every time. Also allows it to scale infinitely.

You could do a simple map, instead of the code you have there in your self-answer:

var numArray = $(':input[name^="ticket_fields"]').map(function(){ fieldId = this.name.replace(/\D/g, ""); if ($.inArray(fieldId,numArray) === -1) return fieldId;
}).get();


Also using this.name instead of \$(this).attr('name'), which is massively inefficient.