patternjavascriptMinor
Form validation library
Viewed 0 times
formvalidationlibrary
Problem
Background:
After reading this thought provoking book I decided to write a small library as an exercise.
I am using Google closure for type checking and advance code optimizations.
I want to check if I am following a good object o
After reading this thought provoking book I decided to write a small library as an exercise.
goog.require('goog.structs.Map');
var MyModule = {};
MyModule.FormHelper = {
/** @type {?Element} */
form: null,
/** @type {goog.structs.Map} */
errors: {},
/** @param {!Element} element */
init: function(formElement) {
this.form = formElement;
},
/**
* @param {!Element} element
* @return {!Array>}
*/
getElementAttributes: function(element) {
if (!element) return [];
return [].slice.call(element.attributes).map(function(attr) {
return {[attr.name]: attr.value};
});
},
/**
* @param {string} filterOn
* @return {!Array}
*/
filterElements: function(filterOn) {
return [].slice.call(this.form.elements).filter(function(element) {
return element.hasAttribute(filterOn);
});
}
};
MyModule.Form = Object.create(MyModule.FormHelper);
MyModule.Form.validate = function() {
/** @type {!Array} */
var elements = this.getRequiredElements();
elements.reduce(function(map, element) {
if (element.value == '') {
map[element.name] = 'Required field cannot be empty';
}
return map;
}, this.errors);
};
MyModule.Form.getRequiredElements = function() {
return this.filterElements('required');
};
MyModule.createForm = function(name) {
/** @type {!Element} */
var formElement = document.forms[name];
if (!formElement) {
throw new Error('Form not found.');
}
var form = Object.create(MyModule.Form);
form.init(formElement);
return form;
};
var contactForm;
var callback = function(e) {
e.preventDefault()
contactForm.validate();
console.log(contactForm.errors);
}
window.onload = function () {
contactForm = MyModule.createForm('ContactForm');
contactForm.form.addEventListener("submit", callback, false); //Modern browsers
}I am using Google closure for type checking and advance code optimizations.
I want to check if I am following a good object o
Solution
Global variables
I know this isn't part of the module and probably just throwaway code, but you should restructure the module usage to avoid making global variables contactForm and callback:
Organization of properties between prototypes
I'm not sure why you'd divide up methods and properties between
This may seem too simple, but your module solves a simple problem. A more complicated module that would benefit from delegation between multiple prototypes would be one that has multiple types of
I don't think you need/want the
Also, a subjective point: I'd rename this property to
I hope this helps! Kyle Simpson's YDKJS books made me think as well, and with ES6 classes growing more common every day, I often wonder how this explicitly prototype-based JavaScript style can coexist with the classes Simpson discredited.
I know this isn't part of the module and probably just throwaway code, but you should restructure the module usage to avoid making global variables contactForm and callback:
window.onload = function () {
var contactForm = MyModule.createForm('ContactForm');
contactForm.form.addEventListener("submit", function onSubmit(e) {
e.preventDefault()
contactForm.validate();
console.log(contactForm.errors);
}, false); //Modern browsers
}Organization of properties between prototypes
I'm not sure why you'd divide up methods and properties between
FormHelper and Form, as they seem to perform very similar functionality. I'd combine them into a single Form object; that's the only prototype you need.This may seem too simple, but your module solves a simple problem. A more complicated module that would benefit from delegation between multiple prototypes would be one that has multiple types of
Element prototypes, with some validation functions shared between Elements and some specific to particular types.form prototype propertyI don't think you need/want the
form: null property on the prototype object. Even though init is a method of the prototype, it's assigning form to the base object (also named form) that exists in the submit handler, and that's what you want - a shared form property would make multiple Forms impossible.Also, a subjective point: I'd rename this property to
formElement or just element, since there are too many forms and Forms running around this code.I hope this helps! Kyle Simpson's YDKJS books made me think as well, and with ES6 classes growing more common every day, I often wonder how this explicitly prototype-based JavaScript style can coexist with the classes Simpson discredited.
Code Snippets
window.onload = function () {
var contactForm = MyModule.createForm('ContactForm');
contactForm.form.addEventListener("submit", function onSubmit(e) {
e.preventDefault()
contactForm.validate();
console.log(contactForm.errors);
}, false); //Modern browsers
}Context
StackExchange Code Review Q#132727, answer score: 2
Revisions (0)
No revisions yet.