Merikanto

一簫一劍平生意,負盡狂名十五年

Angular, a MVC Framework

In this post, I will discuss some basic aspects of the Angular framework, and improvements Angular has brought to the frontend development.


Concepts


AngularJS & Angular

AngularJS is the first version of the Angular Framework, and it’s JavaScript-based. On the other hand, Angular refers to all the releases after the first version, and it’s TypeScript-based.


Directive

Something similar to the concept of Directive is always there since the beginning of browsers and the web.


The Shadow DOM & Built-in Browser Directives

For instance, a plain input field is an example of a browser built-in directive:


If we turn on Show User Agent Shadow DOM under the Dev Tool Settings, we see the implementation as follows:

1
2
3
4
5
6
7
<input placeholder="Type Your Search">
## shadow-root
<div pseudo="-webkit-input-placeholder" id="placeholder"
style="display: block !important; text-overflow: clip;">
Type Your Search
</div>
<div id="inner-editor"></div>

This indicates that the input component is not a native OS input. Instead, the browser internally composes HTML tags of other more primitive HTML tags and styles, like div, until it reaches the very native rendering elements of the native OS where it’s running. These elements are said to be part of the Shadow DOM of the input component.


Shadow DOM

These HTML elements are a hidden document sub-tree that can exist inside of what it looks like a leaf component, such as an HTML input. The CSS styles that run inside this input are isolated: these styles are not visible in the main HTML of the page, they are only visible inside the component.

By using browser built-in features, we can:

  • Define a public XML-like API to an element of the page
  • Define the look and feel of the element using HTML
  • Add behavior to that new element
  • Add CSS to style it while keeping those styles isolated

Therefore, the browser directive means: An internal browser implementation mechanism. The combined specification of a look and feel, an API and a behavior.


Angular Directive

What Angular Core is about:

It’s like a missing toolkit for extending the browser with our own HTML elements, with their own API, look and feel and behavior.

It’s designed to extend HTML instead of replacing it, by providing a TS implementation of some functionality, that until now was only available as an internal browser composition mechanism.

The goal is to define our own HTML elements and use them to compose our application, in a very similar way to what browsers are already doing under the hood.


The MVC Framework

MVC is a software design pattern. This pattern is reflected in server-side frameworks such as Django, Rails, Spring MVC, and client-side frameworks such as Angular.


From Spring MVC to Angular

Form-intensive apps are ideal for being built as single page web apps. The main idea of the architecture below is to build the server as a set of stateless reusable REST services, and from an MVC perspective to take the controller out of the backend and move it into the browser.

The client is MVC-capable and contains all the presentation logic which is separated in a view layer, a controller layer, and a frontend services layer. After the initial application startup, only JSON data goes between client and server.

AngularJs Spring MVC architecture

Backend: Spring MVC

For the router layer, the same Spring MVC annotations used to build a JSP/Thymeleaf application can also be used to build a REST API.

The REST API backend is built with the following layers:

  • Router Layer: defines which service entry points correspond to a given HTTP URL, and how parameters are to be read from the HTTP request. Use @RestController.
  • Service Layer: contains any business logic such as validations, defines the scope of business transactions
  • Persistence Layer: maps the database to domain objects

Note that in the router layer, the controllers do not return a String that defines which view template should be rendered. Instead the @ResponseBody annotation indicates that, controller’s return value should be directly rendered and become the response body. For example:

1
2
3
4
5
6
7
8
@ResponseBody
@ResponseStatus(HttpStatus.OK)
@RequestMapping(method = RequestMethod.GET)

public UserInfoDTO getUserInfo(Principal principal) {
User user = userService.findUserByUsername(principal.getName());
/* ...... */
}

By adding the Jackson JSON library, the returned value will be directly converted to JSON. It’s also possible to convert to XML or other formats, depending on the value of the Accept HTTP header specified by the client.


Frontend: Angular

The frontend should be built around a view-specific model (which is not the domain model), and should only handle presentation logic, but no business logic. The three layers are below:


View Layer

The view layer is composed of HTML templates, CSS, and any Angular directives representing the different UI components.


Frontend Service Layer

A set of Angular services that allow to interact with the backend (e.g. rethe AppComponent code does not generate HTML, it only fetches the data from the backend), and that can be injected into Angular controllers.

The JSON object is the data, also known as the Model, and we would like to display it on the screen - therefore we need to generate HTML based on this Model through the controller layer.


Controller Layer

The controller layer is made of Angular controllers that glue the data retrieved from the backend and the view together. The controller connects view layer & frontend service layer.

One of the main responsibilities of the controller is to perform frontend validations. This is only for user convenience: e.g. to immediately inform the user that a field is required.

Any frontend validations need to be repeated in the backend at the service layer level due to security reasons, as the frontend validations can be easily bypassed.


Angular MVC

  • the plain JSON object is the Model of our Application
  • the template (or the output of its processing) is the View
  • the Angular AppComponent binds the View and the Model together, and it serves as the Controller

jQuery & Angular MVC

Biggest difference between jQuery & Angular:

Angular does not generate HTML and then let browser parse the HTML. Instead, Angular is generating DOM data structures directly.


jQuery

Request for Data (Ajax)

In a jQuery application, the first thing is to query the REST API backend by jQuery Ajax request, and return only the data.

1
2
3
4
5
6
7
8
$(document).ready(function() {
$.get( "https://some-url/pojos.json",
function( data ) {
var pojos = Object.values(data);
console.log(pojos);
...
});
});

Generate the View

After we have the data on frontend, we can use it to create the multiple Views:

Note: The HTML is more than the data. HTML is a particular representation of the Model, that we can call a View, and the same data could have multiple views.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$.get( "https://some-url/pojos.json", 
function(data) {
var pojos = Object.values(data);
var html = "<table class='table pojos-list'>' + " +
"'<thead>" +
"<th>Description</th>" +
"</thead>" +
"<tbody>";

pojos.forEach(function(pojo) {
html += '<tr>' + +
'<td>' + pojo.description + '</td>' + '</tr>'; });

html += '</tbody></table>';
$("#pojos").html(html); });

For a jQuery application, it takes the data model, and transform it into the multiple views of the data. Below are some of the characteristics:

  • Not very readable & maintainable, mixing HTML with JS
  • This is a lot of code, it makes for a significant portion of our application
  • We are building HTML by string concatenation and then passing it on to the browser. But the browser still has to parse it

Improvement in Angular

Now we rewrite the example above using Angular. Important difference between jQuery and Angular (non-MVC & MVC):

In Angular, the Model and the View are clearly separated and interact via the AppComponent class, while in jQuery, all is mixed in the same code.


Request for Data

Compared to jQuery, we see that:

  • The AppComponent fetches the data from the backend, and links the template to generate HTML view
  • HTTP request is being made via the Angular HTTP module
  • Data is stored in a variable called pojos
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Component({
selector: 'app-root',
templateUrl: 'app.component.html'
})

export class AppComponent implements OnInit {
pojos: any[];
constructor(private http:Http) {}

ngOnInit() {
this.http.get('https://some-url/pojos.json')
.map(res => Object.values(res.json()))
.subscribe(pojos => this.pojos = pojos);
}
}

Generate the View

The HTML code is in app.component.html, and it’s separated form the component code. The code is different from the normal HTML we see, and these expressions are how Angular ties the data and the view together.

  • the ngFor directive that loops through the list of lessons

  • the {{pojo.description}} expression, which is how we can output data to the view

1
2
3
4
5
6
7
8
9
10
<table class='table pojos-list'>
<thead>
<th>Description</th>
</thead>
<tbody>
<tr *ngFor="let pojo of pojos">
<td>{{pojo.description}}</td>
</tr>
</tbody>
</table>

Modify app.component

Angular keeps the View in sync with the model for us at all times via its transparent change detection mechanism.

When we make changes, we simply updated the Model, and Angular has reflected the change automatically in the View for us.

We don’t have to write the code that manually synchronizes the Model and the View. That code is generated for us automatically.


Angular generates DOM data structures directly

This works much faster than building manually HTML and then passing it to the DOM for parsing.

By building DOM nodes directly, Angular is bypassing the HTML parsing step altogether. So the browser simply takes the ready to use DOM tree and renders it to the screen.

And more than that, it will do so in an optimal way, by trying to change just the HTML that absolutely needs to be changed:

Angular will not replace the whole DOM tree each time, it updates the DOM in an optimal way, depending on what parts of the Model have changed.


Summary

Advantages of using an MVC framework like Angular:

  • Separation of Concerns

    • Separate Model and View. Use app.component.ts to bind the model and view.
  • Transparent Model to View Synchronization

  • Faster UI Performance

    • The View is modified by generating directly DOM object trees in a cross-browser compatible way, therefore effectively bypassing the parsing step.
    • The HTML still needs to be parsed, but it’s done only once per template by Angular and by the browser each time (JIT Just in Time, or AOT Ahead of Time).
    • CLI: advanced development environment (have all these features and benefits working transparently out of the box)

Problems with NOT using MVC:

  • Choosing to not use an MVC framework means that we will have to keep the Model and the View in sync manually, which looks simple at first sight but very quickly we will end up with an unmaintainable program.

Useful Libraries

PureCSS & SkinBuilder: Easily generate a theme based on a primary color.


Lodash: functional programming library to manipulate data.

Lodash makes JavaScript easier by taking the hassle out of working with arrays, numbers, objects, strings, etc. Lodash’s modular methods are great for:

  • Iterating arrays, objects, & strings
  • Manipulating & testing values
  • Creating composite functions

CSRF Angular: prevent cross-site request forgery attacks.

npm install spring-security-csrf-token-interceptor


Ngx Bootstrap: Bootstrapping Angular components.

npm install ngx-bootstrap --save