Expressjs - MVC

expressjs

http://code.tutsplus.com/tutorials/build-a-complete-mvc-website-with-expressjs--net-34168

How can we create a control panel?

Let's first create a simple controller which will serve as the administration page. /controllers/Admin.js file:

var BaseController = require("./Base"),
    View = require("../views/Base");
module.exports = BaseController.extend({ 
    name: "Admin",
    run: function(req, res, next) {
        var v = new View(res, 'admin');
        v.render({
            title: 'Administration',
            content: 'Welcome to the control panel'
        });
    }
});

By using the pre-written base classes for our controllers and views, we can easily create the entry point for the control panel. The View class accepts a name of a template file. According to the code above, the file should be called admin.hjs and should be placed in /templates. The content would look something like this:

<!DOCTYPE html>
<html>
    <head>
        <title>{{ title }}</title>
        <link rel='stylesheet' href='/stylesheets/style.css' />
    </head>
    <body>
        <div class="container">
            <h1>{{ content }}</h1>
        </div>
    </body>
</html>

Now to make the controller visible, we have to add a route to it in app.js:

var Admin = require('./controllers/Admin');
...
var attachDB = function(req, res, next) {
    req.db = db;
    next();
};
...
app.all('/adminattachDB, function(req, res, next) {
    Admin.run(req, res, next);
});

Note that we are not sending the Admin.run method directly as middleware. That's because we want to keep the context. If we do this:

app.all('/adminAdmin.run);

the word this in Admin will point to something else.

How can we define a model?

// /models/ContentModel.js

var Model = require("./Base"),
    crypto = require("crypto"),
    model = new Model();
var ContentModel = model.extend({
    insert: function(data, callback) {
        data.ID = crypto.randomBytes(20).toString('hex'); 
        this.collection().insert(data, {}, callback || function(){ });
    },
    update: function(data, callback) {
        this.collection().update({ID: data.ID}, data, {}, callback || function(){ });   
    },
    getlist: function(callback, query) {
        this.collection().find(query || {}).toArray(callback);
    },
    remove: function(ID, callback) {
        this.collection().findAndModify({ID: ID}, [], {}, {remove: true}, callback);
    }
});
module.exports = ContentModel;

See http://code.tutsplus.com/tutorials/build-a-complete-mvc-website-with-expressjs--net-34168

The model takes care of generating a unique ID for every record. We will need it in order to update the information later on. If we want to add a new record for our Contacts page, we can simply use:

var model = new (require("../models/ContentModel"));
model.insert({
    title: "Contacts",
    text: "...",
    type: "contacts"
});

So, we have a nice API to manage the data in our mongodb collection.

How can we create the Home controller?

Here is the controller for the Home page - /controllers/Home.js:

module.exports = BaseController.extend({ 
    name: "Home",
    content: null,
    run: function(req, res, next) {
        model.setDB(req.db);
        var self = this;
        this.getContent(function() {
            var v = new View(res, 'home');
            v.render(self.content);
        })
    },
    getContent: function(callback) {
        var self = this;
        this.content = {};
        model.getlist(function(err, records) {
            ... storing data to content object
            model.getlist(function(err, records) {
                ... storing data to content object
                callback();
            }, { type: 'blog' });
        }, { type: 'home' });
    }
});

The home page needs one record with a type of home and four records with a type of blog. Once the controller is done, we just have to add a route to it in app.js:

app.all('/', attachDB, function(req, res, next) {
    Home.run(req, res, next);
});

The other pages for our front-end (client side) are almost identical, in that they all have a controller, which fetches data by using the model class and of course a route defined.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License