HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptModerate

Custom JavaScript validation using the factory / module patterns

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
thejavascriptfactorymodulevalidationpatternscustomusing

Problem

I am in the process of diving a bit deeper into JavaScript development and am looking at some common language patterns (module, and factory in particular). In this code, my aim is to create a re-usable framework for creating custom field validators in JS that can be easily extended. In addition, I want the code that does the validation to NOT have a big conditional logic block that needs to be maintained (for example: if(required) {} elseif(regex) {} elseif(numeric){}, etc....).

The Factory allows new types of validators to be added to its registration at any point, provided they have a common prototype. The particular type of validator can then be instantiated by the factory by passing the name that was registered with that type.

I have segmented the code into separate files as I intend to be able to drop this into projects I'm working on, add any custom validation needed for the application, and move on.

The general flow of the UI is this:

  • When the page first loads, the fields are empty. Because of this, (and the required validation), I have an initial state that prevents the page from showing errors on load.



  • The KnockoutJS binding on the form fields triggers the field validation after each keystroke.



  • If at any point the form is invalid, the field will be highlighted and a "validation summary" will be shown at the top, indicating the state of the form.



  • Any validation errors will cause the form to be unable to submit



For this project, I opted to use knockout.js as a MVVM framework for binding to the UI and making the form responsive.

The Code

I have the following HTML form (in its entirety):

```


JavaScript Validator








var model = new FormViewModel();
$(function() {
ko.applyBindings(model);
});






Form Status:





Validation Testing

First Name:




Last Name:






Solution

This review is mostly about improving the implementation.
I don't know JavaScript enough to answer your big questions.
Try to catch @konijn or @flambino in the 2nd monitor chat room.

Naming

The first most noticeable thing to me is the naming of variables.
I think the convention is to use PascalCase for classes,
and camelCase for variables.

JSHint

If you paste your code to http://jshint.com/,
it points out a couple of interesting issues, most notably:

  • You have CreateInstance twice in the same object: the second will overwrite the first



  • Parentheses () missing when invoking ValidProto in var protoInstance = new ValidProto;, and by the way protoInstance seems to be unused



  • A couple of other minor issues, do see it for yourself and correct all if possible



Simplification

Although I'm against clever tricks that try to make the code super-compact,
I would shorten the code in a couple of places in a not yet too clever way.

Instead of this:

if (self.IsValid()) {
    return "";
} else {
    return self.ValidationMessageFormat().replace("{0}", self.DisplayName());
} // end if/else


I would use a ternary operator:

return self.IsValid() ? "" : self.ValidationMessageFormat().replace("{0}", self.DisplayName());


Instead of this:

var request = new types[type](args);
return request;


Why not simply:

return new types[type](args);


Instead of this:

if(!isNullOrWhiteSpace(data)) {
    self.IsValid(true);
  } else {
    self.IsValid(false);
  } // end if/else


This is much better:

self.IsValid(!isNullOrWhiteSpace(data));


Instead of this:

var oldClass = "";
if(newClass == "invalid") {
  oldClass = "valid";
} else {
  oldClass = "invalid";
} // end if/else


This is better:

var oldClass = newClass == "invalid" ? "valid" : newClass;


Coding style

The // end if/else and such are indeed pretty annoying, as @JaDogg said, just noise in the code.

I would also remove the unnecessary parentheses from around expressions like these:

return (val == null || val == undefined);
return (isNullOrUndefined(val) || val == "" || val.trim() == "");

Code Snippets

if (self.IsValid()) {
    return "";
} else {
    return self.ValidationMessageFormat().replace("{0}", self.DisplayName());
} // end if/else
return self.IsValid() ? "" : self.ValidationMessageFormat().replace("{0}", self.DisplayName());
var request = new types[type](args);
return request;
return new types[type](args);
if(!isNullOrWhiteSpace(data)) {
    self.IsValid(true);
  } else {
    self.IsValid(false);
  } // end if/else

Context

StackExchange Code Review Q#67458, answer score: 11

Revisions (0)

No revisions yet.