Skip to content Skip to sidebar Skip to footer

How To Avoid Duplicate Code For Constraint Validation In The Model And View Of A MVC Web App?

Integrity constraints should be defined in the model classes of a MVC application since they are part of the semantics of a model class (representing a business object type). Howev

Solution 1:

Unfortunately, many MVC application development frameworks do not provide any support for maintaining the integrity constraints code in the model and use it for data validation both in the view (on input and on form submission) and in the model (before save).

I'll try to provide a sketch of the approach that I've developed to solve this multiple validation problem with the HTML5 forms API, and its setCustomValidity and checkValidity methods. Since it requires to execute the same code both in the view and in the model, it only works in a JavaScript MVC web app, where we have the same programming language (JavaScript) in both parts of the app, unlike in other (e.g. PHP od Java) web apps, where the backend model code is not in JavaScript.

Normally we have to validate property constraints only. It's natural, therefore, to write a class-level check function that validates all constraints for each property of a model class. For instance, the following check function makes sure that a value for the ISBN property of a Book object is a 10-digit string or a 9-digit string followed by "X":

Book.checkIsbn = function (isbn) {
  if (typeof(isbn) !== "string" || isbn.trim() === "") {
    return new RangeConstraintViolation("The ISBN must be a non-empty string!");
  } else if (!/\b\d{9}(\d|X)\b/.test( isbn)) {
    return new PatternConstraintViolation(
        'The ISBN must be a 10-digit string or a 9-digit string followed by "X"!');
  } else {
    return new NoConstraintViolation();
  }
};

The check function returns an instance of a ConstraintViolation class, which has a string-valued message property. In the HTML5 form providing the view (or UI), we add an event listener for input events to the form input field concerned for handling the validation on user input:

isbnInpEl.addEventListener("input", function () { 
  isbnInpEl.setCustomValidity( Book.checkIsbn( isbnInpEl.value).message);
});

This event listener invokes the setCustomValidity method, which has a string parameter. We provide the message created by our property check function as the argument for the invocation of setCustomValidity. If it's empty, this means the user input is valid. Otherwise, if it contains a non-empty constraint violation message, the HTML5 browser will take care of indicating the constraint violation to the user (e.g. by showing a red border for the input field and displaying the message).

For handling the validation on form submission button click, we check all input fields of the form by invoking the HTML5 checkValidity method on the form element object:

if (formEl.checkValidity()) {
  // save
  formEl.reset();
}

Finally, for checking the constraints in the model class before saving any new data, we may invoke the check functions in the property setters, as in

Book.prototype.setIsbn = function (isbn) {
  var validationResult = Book.checkIsbn( isbn);
  if (validationResult instanceof NoConstraintViolation) {
    this.isbn = isbn;
  } else {
    throw validationResult;
  }
};

You can find the full example code in my book Building Front-End Web Apps with Plain JavaScript.


Post a Comment for "How To Avoid Duplicate Code For Constraint Validation In The Model And View Of A MVC Web App?"