views:

179

answers:

4

When doing validation in JavaScript, how do I keep validation methods that need to handle a bunch of contingencies from becoming unruly?

For example, I have a form with a field that has validation that checks:

  • is the new value a number?
  • Is the value in another field on the form > 0 when the current field > 0
  • Is another field on the form == 1 and the current field == 0
  • Is another field on the form == true and the current field is Mod another field == 0

Etc.

Currently, I've got a method with a bunch of if/else statements.

I could break each check out into it's own method and call it from the main validation method, but that would create a ton of new methods.

Update: regardless of whether I use a framework or individual methods, am I still resigned to having the calling validation method filled with If/Else or Switch statements with alert boxes for the failing validations?

A: 

I would recommend splitting each individual check out into its own method, with controls to be validated passed in as arguments. That way you can reuse the common ones pretty easily ("is the new value a number?").

I'm not aware of any downside to having a large number of methods in JavaScript (other than namespace crowding), but I could be missing something there.

Of course, you may also want to look into using a framework of some kind.

AaronSieb
+3  A: 

Why re-invent the wheel? I would suggest the jQuery Validation Plugin. Check out the demo pages as well

Phill Pafford
+1  A: 

Sounds like you might want a rudimentary state machine. One thing you might consider is breaking the validators into the simplest forms:

function validator(op, options, pass, fail) {
    if (op(options)) {
        pass(options);
    } else {
        fail(options);
    }
}

Then you can chain them together to form more complex systems.

function isFooChecked(options) {
    return $(options.foo).is(':checked');
}

function sayHi(options) {
    alert('hi ' + options.name);
}

function fail(options) {
    alert(options.name + ' was bad');
}

function validateName() {
    validator(isFooChecked, { foo: '#someField', name: $('#nameField').val() }, sayHi, fail);
}

You'll still have a lot of code, but if you do it right, functions should be small and easy to understand.

swilliams
A: 

I have a Json object which looks like

{'field1': {'rule_name1':{'rule': rule1, 'message': message1},
    {'rule_name2':{'rule': rule2, 'message': message2}},
    field2: {'rule_name3':{'rule': rule3, 'message': message3},
    {'rule_name4':{'rule': rule1, 'message': message1}},
    {'rule_name5':{'rule': rule4, 'message': message4}}}

or, if you find it more readable

field1
    rule_name1
        rule: rule1
        message: message1
    rule_name2
        rule: rule2
        message: message2
field2
    rule_name3
        rule: rule3
        message: message3
    rule_name4
        rule: rule1
        message: message1
    rule_name5
        rule: rule4
        message: message4

Basically, you have a list of fields. Under each field you find a list of rules, whose names are irrelevant, and for each rule_name you have a rule and a message.

Every time I need to check a field, I find the corresponding subobject. Then I iterate over the rule_names, and for rule_name I get a rule and a message. The rule corresponds to a method which checks the field (for instance "notEmpty()"). So I call the method: if it returns true, I carry the iteration to next rule_name. Otherwise I return the message.

Then I can use the message as I want in a view method.

Andrea