The term Model-View-Controller has been in use since the late 1970s and arose from the Smalltalk project at Xerox PARC where it was conceived as a way to organize some early GUI applications. Some of the fine detail of the original MVC pattern was tied to Smalltalk-specific concepts, such as screens and tools, but the broader ideas are still applicable to applications, and they are especially well-suited to web applications.
The MVC pattern first took hold in the server-side end of web development, through toolkits like Ruby on Rails and the ASP.NET MVC Framework. In recent years, the MVC pattern has been seen as a way to manage the growing richness and complexity of client-side web development as well, and it is in this environment that Angular has emerged.
The key to applying the MVC pattern is to implement the key premise of a separation of concerns, in which the data model in the application is decoupled from the business and presentation logic. In clientside web development, this means separating the data, the logic that operates on that data, and the HTML elements used to display the data. The result is a client-side application that is easier to develop, maintain, and test.
The three main building blocks are the model, the controller, and the view. In the following picture, you can see the traditional exposition of the MVC pattern as it applies to server-side development.
You can see that the expectation is that the model is obtained from a database and that the goal of the application is to service HTTP requests from the browser. This is the basis for round-trip web apps, which I described earlier.
Of course, Angular exists in the browser, which leads to a twist on the MVC theme, as illustrated in the following picture.
The client-side implementation of the MVC pattern gets its data from server-side components, usually via a RESTful web service. The goal of the controller and the view is to operate on the data in the model to perform DOM manipulation so as to create and manage HTML elements that the user can interact with. Those interactions are fed back to the controller, closing the loop to form an interactive application.
Angular uses slightly different terminology for its building blocks, which means that the MVC model implemented using Angular looks more like in the picture.
The figure shows the basic mapping of Angular building blocks to the MVC pattern. To support the MVC pattern, Angular provides a broad set of additional features, which I describe throughout the website.
Models—the M in MVC—contain the data that users work with. There are two broad types of model: view models, which represent just data passed from the component to the template, and domain models, which contain the data in a business domain, along with the operations, transformations, and rules for creating, storing, and manipulating that data, collectively referred to as the model logic.
You can’t read a definition of the MVC pattern without tripping over the word business, which is unfortunate because a lot of web development goes far beyond the line-of-business applications that led to this kind of terminology. Business applications are still a big chunk of the development world, however, and if you are writing, say, a sales accounting system, then your business domain would encompass the process related to sales accounting, and your domain model would contain the accounts data and the logic by which accounts are created, stored, and managed. If you are creating a cat video website, then you still have a business domain; it is just that it might not fit within the structure of a corporation. Your domain model would contain the cat videos and the logic that will create, store, and manipulate those videos.
Many Angular models will effectively push the logic to the server-side and invoke it via a RESTful web service because there is little support for data persistence within the browser, and it is simply easier to get the data you require over Ajax.
- Contain the domain data
- Contain the logic for creating, managing, and modifying the domain data (even if that means executing remote logic via web services)
- Provide a clean API that exposes the model data and operations on it
The model should not
- Expose details of how the model data is obtained or managed (in other words, details of the data storage mechanism or the remote web service should not be exposed to controllers and views)
- Contain logic that transforms the model based on user interaction (because this is the component’s job)
- Contain logic for displaying data to the user (this is the template’s job)
The benefits of ensuring that the model is isolated from the controller and views are that you can test your logic more easily and that enhancing and maintaining the overall application is simpler and easier.
The best domain models contain the logic for getting and storing data persistently and the logic for creating, read, update, and delete operations (known collectively as CRUD) or separate models for querying and modifying data, known as the Command and Query Responsibility Segregation (CQRS) pattern.
Controllers, which are known as components in Angular, are the connective tissue in an Angular web app, acting as conduits between the data model and views. Components add business domain logic required to present some aspects of the model and perform operations on it. A component that follows the MVC pattern should
- Contain the logic required to set up the initial state of the template
- Contain the logic/behaviors required by the template to present data from the model
- Contain the logic/behaviors required to update the model based on user interaction
A component should not
- Contain logic that manipulates the DOM (that is the job of the template)
- Contain logic that manages the persistence of data (that is the job of the model)
Understanding View Data
The domain model isn’t the only data in an Angular application. Components can create view data (also known as view model data or view models) to simplify templates and their interactions with the component.
Views, which are known as templates in Angular, are defined using HTML elements that are enhanced by data bindings. It is the data bindings that make Angular so flexible, and they transform HTML elements into the foundation for dynamic web applications. I explain the different types of data bindings that Angular provides in detail in Part 2. Templates should
- Contain the logic and markup required to present data to the user
Templates should not
- Contain complex logic (this is better placed in a component or one of the other Angular building blocks, such as directives, services, or pipes)
- Contain logic that creates, stores, or manipulates the domain model
Templates can contain logic, but it should be simple and used sparingly. Putting anything but the simplest method calls or expressions in a template makes the overall application harder to test and maintain.