Computer scienceBackendNode.jsApplication DevelopmentArchitecture of Node.js applications

MVC with Node.js

5 minutes read

The MVC (Model-View-Controller) pattern is a software architectural pattern commonly used in web development to separate the concerns of an application into three distinct components: the model, the view, and the controller. Node.js is a versatile runtime environment that you can use to implement the MVC pattern. In this topic, you will learn about each component of MVC and see a small example that implements the MVC pattern.

Let's start by briefly checking each component in the context of Node.js.

Model

The model represents the data and business logic of the application. It encapsulates the application's data structure, access methods, and validation rules. In Node.js, you can define your models using frameworks like Mongoose (for MongoDB) or Sequelize (for SQL databases). These frameworks provide an abstraction layer to interact with the database and define models with properties, relationships, and methods.

Here's a model example with plain JavaScript:

const books = [];

class Book {
  constructor(title, author) {
    this.title = title;
    this.author = author;
  }

  static getAllBooks() {
    return books;
  }

  static addBook(book) {
    books.push(book);
  }
}

module.exports = Book;

In this example, we define a Book class with a constructor that takes in title and author as parameters. The constructor assigns these values to the respective properties of the Book instance. Also, the Bookclass provides static methods to get all books and add a new book. Finally, we export the Book model so that it is usable in a controller.

The reason for creating a Book model is to encapsulate the data and behavior related to books in a structured and organized manner. The Book model represents the concept of a book within the application and provides a blueprint for creating book objects. So, you can use this model to create new Book objects, validate and manipulate Book data, and reuse the model in different parts of your code, such as the controller.

View

The view is responsible for rendering the user interface and presenting data. In Node.js, you can use templating engines like Handlebars, EJS, or Pug, which are available as Node.js packages, to generate dynamic HTML pages. Views are typically separate files that contain HTML markup with placeholders for dynamic data. The controller, which you will learn about in the next section, passes data to the view, and the view will render it accordingly. For now, think of controller as the bridge between the data(model) and the view.

Continuing from the previous example, here's the example for view:

<!-- Book View -->
<!DOCTYPE html>
<html>
<head>
  <title>Book List</title>
</head>
<body>
  <h1>Book List</h1>
  <div id="bookList">
    <p>No books available.</p>
  </div>
  <form id="addBookForm">
    <input type="text" id="titleInput" placeholder="Book Title" required>
    <input type="text" id="authorInput" placeholder="Author" required>
    <button type="submit">Add Book</button>
  </form>

  <script src="controller.js"></script>
</body>
</html>

The view is an HTML file (book.html) with placeholders for the book list and the form inputs. The snippet above contains id attributes associated with relevant elements to allow us to select them in JavaScript.

Controller

The controller acts as an intermediary between the model and the view. It receives user input from the view, interacts with the model to retrieve or modify data, and updates the view accordingly. In Node.js, you can define your controllers as separate modules or classes that handle specific routes or actions. The controller is responsible for processing incoming requests, validating data, and coordinating the flow of information between the model and the view.

Take a look at the following controller example for the Book model:

const Book = require('./book');

const bookListContainer = document.getElementById('bookList');
const addBookForm = document.getElementById('addBookForm');
const titleInput = document.getElementById('titleInput');
const authorInput = document.getElementById('authorInput');

function renderBookList() {
  const books = Book.getAllBooks();
  bookListContainer.innerHTML = '';

  if (books.length === 0) {
    bookListContainer.innerHTML = '<p>No books available.</p>';
  } else {
    const ul = document.createElement('ul');
    books.forEach(book => {
      const li = document.createElement('li');
      li.textContent = `${book.title} by ${book.author}`;
      ul.appendChild(li);
    });
    bookListContainer.appendChild(ul);
  }
}

addBookForm.addEventListener('submit', event => {
  event.preventDefault();
  const title = titleInput.value;
  const author = authorInput.value;
  const book = new Book(title, author);
  Book.addBook(book);
  renderBookList();
  titleInput.value = '';
  authorInput.value = '';
});

renderBookList();

The controller (controller.js) renders the book list. It handles the function of adding a new book when the form is submitted and updating the view accordingly. It also listens for the submit event on the form and prevents the default form submission behavior. Finally, it creates a new Book instance, adds it to the model, and re-renders the book list.

For the sake of simplicity, the above example is more suited for a client-side application rather than a typical server-side Node.js application. In a server-side Node.js application, like an API, the controller would be responsible for sending and receiving data, validating and authenticating users, etc.

To run this application, you can open the book.html file in a web browser. The book list will be displayed and you can use the form to add new books.

Output of MVC example program

To implement the MVC pattern in Node.js in more practical applications, you would typically set up your routes to map to specific controller actions. When a request is received, the corresponding controller action is invoked, which interacts with the model and prepares the data to be passed to the view. The view then renders the data and sends the response back to the client.

Conclusion

Overall, the MVC pattern helps organize code, separate concerns, and promote code reusability and maintainability in Node.js applications. You've looked at each component that forms the MVC pattern: The model that contains the data of the application, the view that displays the data, and the controller that acts as a bridge between the model and view. To understand how these three components are related, you've looked at a Book management example using the MVC pattern.

7 learners liked this piece of theory. 0 didn't like it. What about you?
Report a typo