How to: MVC structure in plain JavaScript

Most likely you have already heard of AngularJS, or already joined the craze. When I decided to give a course on AngularJS, we decided it would be wise to start with the basics, and as a result I set up a course to develop a single-page application (SPA) without using any frameworks. This course provides the basics so you can understand how AngularJS works. To reach this goal I introduced the concept of Controllers, Models and Services.

The challenge here is how to structure your code, and I wanted to share my thoughts. Especially since I could not find a coherent sample thus far.

For those of you who are not familiar with MVC: it is a development paradigm that stand for “Model View Controller”. Starting with Ruby on Rails, this is now a very popular way to structure application code, it separates concerns. Both Microsoft MVC (backend) and AngularJS (frontend) are MVC frameworks.
Below I will also introduce the concept of Service. This helps to abstract communication to external systems. Though there is much debate on whether this should be done from the Model or from the Controller, my personal preference is to put it at the Controller so all logic is defined in one place.

First a small piece of context. Your Models are basically objects that only have properties. They represent your domain model objects. Controllers define all methods used in your application, basically they coincide with the events triggered from the View (your html page). Services define communication methods with external systems such as local storage or Rest API, to be called by the Controllers.

The example below is a resume that lists the assignments you’ve done. It contains:

  • The view, which is the html file.
  • an assignment Model.
  • a resume Controller. It has an internal storage for the assignments, but is only addressed through methods.
  • Application logic to create the controller and binds controllers to the views.

A last shout out should be given to the wrapping function. It is good practice to get your objects out of global scope to avoid cluttering the document object and accessibility to your code. When using jQuery the document ready event can fulfill this role perfectly.

$(document).ready(function(){
	// 1. Models
	var Assignment = function(company,role,description,conclusion){
		this.Company = company;
		this.Role = role;
		this.Description = description;
		this.Conclusion = conclusion;
	};
 
	// 2. Controllers
	var ResumeController = function(){
		this.assignments = [];
	};
	ResumeController.prototype.addAssignment = function(assignment){
		this.assignments.push(assignment);
		this.refreshList();
	};
	ResumeController.prototype.refreshList = function(){
		$("#list").empty();
		for (var i=0; i < this.assignments.length; i++) {
			$("#list").append("<tr><td>" + this.assignments[i].Company + "</td></tr>");
		}
	};
 
	// 3. Link Controllers to View
	var controller = new ResumeController();
	$("#button").click(function(){
		var assignment = new Assignment(
			$("#company").val(),
			$("#role").val(),
			$("#description").val(),
			$("#conclusion").val()
		);
		controller.addAssignment(assignment);
	});
});

 

<!DOCTYPE html>
<html>
	<head>
		<link href="structure.css" rel="stylesheet" type="text/css" />
		<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.1.min.js"></script>
		<script src="structure.js"></script>
	</head>
	<body>
		<article>
			<h1>Resume</h1>
			<table id="list">
				<tr>
					<td>No content</td>
				</tr>
			</table>
		</article>
		<article>
			<h1>Create new assignment</h1>
			<table>
				<tr>
					<td>Company</td>
					<td><input type="text" id="company" /></td>
				</tr>
				<tr>
					<td>Role</td>
					<td><input type="text" id="role" /></td>
				</tr>
				<tr>
					<td>Description</td>
					<td><textarea id="description"></textarea></td>
				</tr>
				<tr>
					<td>Conclusion</td>
					<td><input type="text" id="conclusion" /></td>
				</tr>
				<tr>
					<td><div id="button">Add</div></td>
				</tr>
			</table>
		</article>
	</body>
</html>

 

#button{
	padding: 10px;
	background-color: blue;
	border-radius: 5px;
	color: white;
	cursor: pointer;
}

 

Should you want to separate the code in different files, look at the Factory pattern. Using this pattern it will start to feel like working on an AngularJS project, except you have to write your own bindings and application logic.

I hope you will enjoy this and gives a good starting point. Enjoy!

Facebooktwitterredditpinterestlinkedinmail

Leave a Reply