Chapter 15. Subtyping in an AngularJS Front-End App

Table of Contents

1. Subtyping with Constructor-Based Classes
1.1. JavaScript Code Pattern
1.2. Using Angular Factory for Subtyping
2. Setup Folder Structure
3. Case Study 1: Eliminating a Class Hierarchy
3.1. Encode the Factory Book
3.2. Write the View and Controller Code
4. Case Study 2: Implementing a Class Hierarchy
4.1. Make the JavaScript class model
4.2. Make the JSON table model
4.3. New issues
4.4. Encode the Angular Factories
4.5. Write the View and Controller Code
5. Run the App and Get the Code

Whenever an app has to manage the data of a larger number of object types, there may be various subtype (inheritance) relationships between some of the object types. Handling subtype relationships is an advanced issue in software application engineering. It is often not well supported by application development frameworks.

To encode the subtyping Angular offers a way that using Services. An Angular factory represents a service, which is defined with an Angular module by ourself. Each factory generates a single object and some functions, that can be injected into any component.

In this chapter of our tutorial, we first explain the general approach to constructor-based Class Hierarchy in JavaScript and introduce the Angular-based subtyping before presenting two case studies based on fragments of the information model of our running example, the Public Library app, shown above. Besides, for focusing more on subtyping, we will ignore the issue of constraint validation.

In the first case study, we consider the single-level class hierarchy with root Book shown in Figure 15.1 below (which is an incomplete disjoint segmentation) . We use the Class Hierarchy Merge design pattern for refactoring this class hierarchy to a single class that is mapped to a persistent database table stored with Parse cloud storage.

Figure 15.1. The object type Book as the root of a disjoint segmentation

The object type Book as the root of a disjoint segmentation

In the second case study, we consider the multi-level class hierarchy consisting of the Person roles Employee, Manager and Author, shown in Figure 15.2 below. We use the Joined Tables Inheritance approach for mapping this class hierarchy to a set of database tables that are related with each other via foreign key dependencies.

Figure 15.2. The Person roles hierarchy

The Person roles hierarchy

In both cases we show

  1. how to derive a JavaScript class model, and a corresponding JSON table model, from the class hierarchiy (representing an information design model),

  2. how to encode the JavaScript class model in the form of JavaScript model classes using Angular factory,

  3. how to write the view and controller code based on the Angular factories.

1. Subtyping with Constructor-Based Classes

1.1. JavaScript Code Pattern

Since JavaScript does not have an explicit class concept, subtyping is not directly supported, but certain forms of subtyping can be implemented with the help of certain code patterns.

We summarize the 3-part code pattern for defining a superclass and a subclass In a constructor-based class hierarchy with the help of an example, illustrated in Figure 15.3 below:

// (1) Define superclass
function Person( first, last) {
  this.firstName = first; 
  this.lastName = last; 
}
// (2) Define subclass
function Student( first, last, studNo) {
  // invoke superclass constructor
  Person.call( this, first, last);
  // define and assign additional properties
  this.studNo = studNo;
}
// (3) Inherit methods from superclass
Student.prototype = Object.create( Person.prototype);
// adjust the subtype's constructor property
Student.prototype.constructor = Student;

Figure 15.3. Student is a subclass of Person

Student is a subclass of Person

1.2. Using Angular Factory for Subtyping

For getting a better code structure, we should define a new Angular module to collect all factories and name it myModles:

var myModels = angular.module('myModels', []);

Don't forget to inject our new module to the main web app module. Suppose we had an Angular Web App named myApp:

var myApp = angular.module('myApp', ['myModels']);

Again, we use Person and Student for instance. First define a factory Person with a constructor function and a update method:

myModels.factory('Person', function() {
  function Person () {
    this.id = 0;
    this.name = "";
  }
  Person.update = function ( slots) {
    this.id = slots.id;
    this.name = slots.name;
  };
  return Person
});

Then, define another factory Student and inject the factory Person:

myModels.factory('Student', [ 'Person', function ( Person) {
  function Student () { 
    Person.call( this);
    this.studNo = "";
  }
  Student.prototype = Object.create( Person.prototype);
  Student.prototype.constructor = Student;
  Student.update = function ( slots) {
    Person.update( slots);
    this.studNo = slots.studNo;
  };
  return Student;
}]);