MVC Architectural Design Pattern With Vanilla JS
Tags: designpattern, generalconcepts
Published: 2022-01-05 17:42:01

---
title: MVC Architectural Design Pattern With Vanilla JS
published: true
date: 2022-01-05 11:15:42 UTC
tags: DesignPattern,GeneralConcepts
series: DesignPattern,GeneralConcepts
canonical_url: https://www.underthehoodlearning.com/mvc-architectural-design-pattern-with-vanilla-js
cover_image: https://res-2.cloudinary.com/under-the-hood-learning/image/upload/q_auto/v1/blog_images/MVC-Vanilla-JS.png
---

Most people assume that the meaning of **MVC (Model-View-Controller)** is static, but that's simply not true. MVC is not a well-defined concept, so do not assume it to be one in conversations. Instead, treat it more like a ***buzzword*** like "cloud".😉 MVC takes on a slightly different meaning depending on the specific context. Without a context, it is only a "fuzzy" concept in general.

MVC is one of the most well-known architectural patterns and is the basis of many JavaScript frameworks (such as **Angular** ) and several server-rendered web frameworks (such as **ASP.NET Core MVC** ) **.** As suggested by the post title, in this article, we will discuss the **MVC pattern** in the context of ***client-side development using JavaScript***.

<!--kg-card-begin: markdown-->

> In this article, we will:
> 
> - briefly explore the original meaning of the MVC pattern by looking at its history
> - explore the meaning of the MVC pattern in the context of JavaScript frontend development
> - implement the MVC architectural pattern using only Vanilla JS on the frontend to gain a deep understanding and hands-on experience with this design pattern

<!--kg-card-end: markdown-->
## History of MVC

The MVC pattern was invented by **Trygve Reenskaug** while he was a visiting scientist at the **Smalltalk** group at the **Xerox Palo Alto Research Center (PARC).** He wrote his first paper on MVC in 1978. The MVC pattern was invented long before the first web browser and was first implemented as part of the **Smalltalk-80** class library. It was originally used as an architectural pattern for creating ***graphical user interfaces (GUIs).***

The original meaning of the **Model-View-Controller** pattern was very different than the meaning associated with the pattern today. In the context of a GUI,  the Model View Controller pattern was interpreted as follows:

- **Model:** A particular piece of data represented by an application, _e.g. weather station temperature reading._
- **View:** One representation of data from the model. The same model might have multiple views associated with it. The views are associated with a particular model through the **Observer** relationship. For example, a temperature reading might be represented by both a label and a bar chart.
- **Controller:** Collects user inputs and modifies the model, _e.g. the controller might collect mouse click events and update the model._

The primary benefit of this original version of the MVC pattern is a ***Separated Presentation,*** which was defined by **Martin Fowler** as:

> A pattern that is used to ensure that any code that manipulates presentation only manipulates representation, pushing all domain and data source logic into clearly separated areas of the program.

In this pattern, the **view** is updated indirectly from the **model** via event handling. The **controller** does not interact directly with the **view.** Instead, the **controller** modifies the **model,** and since the **view** is observing the **model,** the **view** gets updated.

## Why MVC?

To really appreciate the beauty of the MVC pattern, let's look at an example of code without MVC.

The traditional server-rendered web pages consist of static HTML documents. Each time the user requests a page, the server returns a new HTML page with the state of the information on the server at that moment in time. Then, **AJAX** came along allowing us to update page elements and send user requests back to the server without having to wait for the server. However, AJAX development and adoption also brought with it more complexity in our code that required some sort of code restructuring for separation of concern, modularity, and reusability.

Consider the following example. We have a simple form with a single textbox to allow the user to enter their email address for account registration. We will need to set up some validation logic for our form. In this case, the ***event handler*** function for the **Submit** button in the script loops through a predetermined list of fields and run through the validation logic for each of the fields based on the class name metadata. Go ahead and try to click **Submit** without any email address entered. You should see an alert dialog pop up with the warning.👇

<iframe id="cp_embed_abyaOXJ" src="https://codepen.io/underthehoodlearning/embed/preview/abyaOXJ?default-tabs=js%2Cresult&amp;height=300&amp;host=https%3A%2F%2Fcodepen.io&amp;slug-hash=abyaOXJ" title="JS MVC" scrolling="no" frameborder="0" height="300" allowtransparency="true" style="width: 100%; overflow: hidden;"></iframe>

Although this approach works, it isn't very flexible. What if we want to add fields or validate a different form on another page. We would have to duplicate most of this functionality for each new field we add. Also, what if our validation logic is much more complicated than this, _e.g. a field is required only if another field is completed?_ You can probably imagine that our code would eventually grow out of control.😵

## MVC with Vanilla JS

Most of you are familiar with **Single-Page Applications (SPA) MVC** frameworks such as **Angular** that have become increasingly popular over the past few years. However, it's possible to implement the MVC architectural pattern on the front-end without using a framework or library. One of the benefits of this exercise is that it provides you with a solid understanding of how this pattern is implemented _"under the hood"_ so that when it's time for you to pick up a framework, you feel more comfortable understanding why it works the way it does. Without further ado, let's get started!😎

### Build the View, Model, Controller

Before we dive into the code, below is a demo of what we will be building for this example. Try clicking on the word "Hello" and observe how the text is dynamically updated to "World". Feel free to look at the files to familiarize yourself with the MVC structure.👇

<iframe width="1000" height="500" src="https://codesandbox.io/embed/vanillajs-mvc-30eif" style="width:1000px; height:500px; border:0; border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"></iframe>

In the context of our frontend JS application, **MVC** is an architecture with three layers:

- **Model:** is the container of our state and also performs business/domain logic.
- **View:** is the visual representation of the models, _i.e. the output displayed to the user_ 
- **Controller:** serves as the mediator between the **model** and the **view** and also stores some non-domain application states.

### The View

For a browser-based, vanilla JS implementation, we have **HTML** and the **DOM** to worry about, so there will be two pieces to our **view:** the **HTML** itself and a **View class** that encapsulates relevant **DOM** selectors.

In our example, the **HTML** is very simple. It has the `<h1>` element with the `id=heading`, and references several scripts containing all of our code for the **model, view,** and **controller**. The initial value for the `<h1>` element's `innerText` will be set by the **Controller** as you shall see later.

<!--kg-card-begin: markdown-->
```
<html>
  <head>
    <meta charset=”utf-8">
    <meta name="”viewport”" content="”width" ="device-width”" />
    <title>MVC Experiment</title>
    <script src="./src/index.js"></script>
    <script src="./controllers/heading.controller.js"></script>
    <script src="./models/heading.model.js"></script>
    <script src="./views/heading.view.js"></script>
  </head>

  <body>
    <h1 id="heading"></h1>
  </body>
</html>

```
<!--kg-card-end: markdown-->

Our **View** class is defined in the `heading.view.js` file. We're passing a **controller** into the constructor as a ***dependency.*** The controller will be listening for ***events*** on our relevant **DOM nodes.** Here, we're interested in the `<h1>` DOM node with the `id=heading`. So, we populate the initial value for the `innerText` of this `<h1>` element to the initial state of the **model,** and we do that via the **controller.**

We also register the ***event handler*** for the `<h1>` element via the `addEventListener()` method of the `EventTarget` interface available in the **Web API.** This interface can be implemented by any object that can receive events such as ***element, document, window,*** _etc._ The `addEventListener()` method sets up a function that will be called whenever the specified event is delivered by the target. In this case, we're passing in `click` as the ***event type*** to listen for and the `controller` itself as an object that implements the `EventListerner` interface as you shall see in the section about the **controller.**

<!--kg-card-begin: markdown-->
```
class HeadingView {
  constructor(controller) {
    this.controller = controller;
    this.heading = document.getElementById("heading");
    this.heading.innerText = controller.modelHeading;
    this.heading.addEventListener("click", controller);
  }
}

export { HeadingView };

```
<!--kg-card-end: markdown-->
### The Model

Our **model** is defined in the `heading.model.js` file. For this example, our **model** will be very simple. It consists of a value for the heading, which is what we used to set our `<h1>` element's `innerText`. The model will be ***injected*** into the **controller** so that the controller can manipulate the model as prompted by the **view's events.**

<!--kg-card-begin: markdown-->
```
class HeadingModel {
  constructor() {
    this.heading = "Hello";
  }
}

export { HeadingModel };

```
<!--kg-card-end: markdown-->
### The Controller

As mentioned in the section about the **View,** in order for the event handler to work as expected, the **controller** must implement the `EventListener` interface of the **Web API.** This interface represents an object that can handle an event dispatched by an `EventTarget` object (in this case, it's the `<h1>` element). Any object that uses this interface (in this case, it's the **controller** ) must implement the `handleEvent` method, which is a function that is called whenever an event of the specified type occurs.

Our **controller** is defined in the `heading.controller.js` file.

<!--kg-card-begin: markdown-->
```
class HeadingController {
  constructor(model) {
    this.model = model;
  }

  //EVENTLISTENER INTERFACE
  handleEvent(e) {
    e.stopPropagation();
    switch (e.type) {
      case "click":
        this.clickHandler(e.target);
        break;
      default:
        console.log(e.target);
    }
  }

  get modelHeading() {
    return this.model.heading;
  }

  //CHANGE THE MODEL
  clickHandler(target) {
    this.model.heading = "World";
    target.innerText = this.modelHeading;
  }
}

export { HeadingController };

```
<!--kg-card-end: markdown-->

As shown in the code above, our **controller** implements three methods:

- `handleEvent`: This method handles the `click` event for the `<h1>` element. If the event is `click` then the `clickHandler()` method is called.
- `clickHandler`: This method updates the **model** as well as the `<h1>` element's `innerText` (represented as the `target` parameter).
- `getModelHeading`: This method is used to retrieve the current value of the heading property of the model. As mentioned in the **View** section, we call this method to get the initial state of the model and assign the returned value to the `<h1>` element.

### Wiring Up Model-View-Controller

Now that we have our **model, view,** and **controller** defined, we need to create and inject them in the correct order. We'll do that in the `index.js` file.

<!--kg-card-begin: markdown-->
```
import { HeadingModel } from "../models/heading.model";
import { HeadingController } from "../controllers/heading.controller";
import { HeadingView } from "../views/heading.view";

function main() {
  var model = new HeadingModel();
  var controller = new HeadingController(model);
  var view = new HeadingView(controller);
}

main();

```
<!--kg-card-end: markdown-->

The **model** is instantiated first, injected into the constructor for the **controller,** and then the **controller** is injected into the **view.** Our **model** does not know anything about the **view** and vice versa. The **controller** can interact with both since it's injected into the **view,** and the **model** is injected into the **controller.** Finally, we invoke the `main()` function and we should be able to click "Hello" to change it to "World".

And there you have it. We've learned how to structure our code following the **MVC** pattern using just Vanilla JS. Sure, we ended up with more code than what we had in the example without using MVC, but the idea is that this pattern can be expanded to make your code more modular and maintainable as your application grows in its complexity.

We can stop here, but I think we can expand on these building blocks to make it even better by implementing the **Observer** pattern to achieve a ***unidirectional data flow*** between the **model** and the view. We can also add the ability to toggle between "Hello" and "World" by implementing the **State** pattern. Going through these exercises would also help us learn about these two design patterns ( **Observer** and **State** patterns) in the most practical way. So let's do that in the next two articles.💪