Your First JavaScript App – IV
Read the first part of this series.
In the previous post, we had initialised the contacts manager module, but we haven’t created it yet. We will create one now. We already know that we should add one init
function to contactsManager
object and this object should be available on the window
object.
We will create an object called contactsManager and add it to global scope, i.e. window.
// scripts/modules/contacts/contacts.js
var contactsManager = {
init: function () {
console.log ('Contacts Manager Initialised.');
}
};
window.contactsManager = contactsManager;
You can get rid of the console.log
statement later. If you open your index.html in browser, and if you look at the console, you’ll see this message printed there.
We will return to this file and update it, because we don’t have anything (model, view, and, controller) to use. In the next bit, we will just create the skeleton for all the other files, and return to complete the initialisation.
// scripts/modules/contacts/contactsModel.js
var ContactsModel = (function () {
function CModel () {}
return CModel;
}) ();
// scripts/modules/contacts/contactsView.js
var ContactsView = (function () {
function CView () {}
return CView;
}) ();
// scripts/modules/contacts/contactsController.js
var ContactsController = (function () {
function CCtrl (model, view) {}
return CCtrl;
}) ();
These three files are almost
Why this structure?
This is one way of creating a module, you may find a different one in a different place.
We are using IIFEs to create our constructor functions and assign it to a variable. For example, ContactsView
gets the CView
which is returned by the IIFE. Note that CView
is also a function, and we will use it to create an instance/object of CView
.
Though in later parts you will see and understand why we need this extra layer for creating a constructor
function inside IIFE, instead of writing something like this,
// not using it, read above paragraph.
var ContactsView = function () {}
The reason is, we want to hide the implementation from the global scope. Now this ContactsView
is in global scope and, we need it to be in global scope. But what about some function, let’s say, renderMessage
for example. If this function is also in global scope, anyone can execute it from console. You must have read in past that we create scopes using function and outer scope cannot scope inner scope’s data.
Compare following codes:
// method 1
// begin
var ContactsView = function () {}
function renderMessage () {}
// end
In the above code, both ContactsView
and renderMessage
is global. Now check this,
// method 2
// begin
var ContactsView = (function () {
function CView () {}
function renderMessage () {}
return CView;
})();
// end
While in this code, ContactsView
which is global, has the value and access of CView
. renderMessage
is hidden from global scope.
Initialise Module
Now that we have mode, view, and, controller available. Let’s complete the initialisation.
// scripts/modules/contacts/contacts.js
var contactsManager = {
init: function () {
new ContactsController (new ContactsModel (), ContactsView ());
}
};
window.contactsManager = contactsManager;
Alternatively, we could do this, but we really don’t need a reference for created model and view.
// Not using this
var contactsManager = {
init: function () {
var model = new ContactsModel ();
var view = new ContactsView ();
var ctrl = new ContactsController (model, view);
}
};
window.contactsManager = contactsManager;
Note: You may try and print some message in all the constructor functions to see if all of them got initialised.
Creating a simple MVC example
Before moving forward, let’s create a small example, through which we will try to use the MVC structure. This example can be a base for all the other parts and functionality of the application.
We already know that the model is responsible for providing data, the view is for rendering that data on a webpage and the controller is the one which controls this flow. So let’s go ahead and code this.
Model
function CModel () {
this.message = 'Hello from Model!'
}
In the constructor function of the model, we have created and added a property model this
CModel
message
will be added to the object.
View
CView.prototype.render = function (message, parentNode) {
var div = document.createElement ('div'),
text = document.createTextNode (message);
div.appendChild (text);
parentNode.appendChild (div);
}
In general everything that can be shared, gets added to prototype. We do not want to create multiple instances of render function and allocate memory for it. The idea of creating a function is to re-use. So every object CView
Controller
function CCtrl (model, view) {
this.model = model;
this.view = view;
var rootNode = document.getElementById ('root');
this.view.render (this.model.message, rootNode);
}
During initialisation, we had passed an object of the model and an object of the view to the constructor function of the controller. We have used them and assigned to this.model
this.view
this.view
CView
message
model
and the root node
which we had created in the HTML
page.
Here is the summary of what we did until now,
- create a model, add some data.
- create a view, add a render function.
- create a controller by passing an instance of the model and view.
- initialise the module by creating the controller in the initialiser [entry point function].
In the next post, we will discard this example and start building our application.
Leave a Reply