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

Form validation library

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

Problem

Background:

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:

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 property

I 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.