Tutorial: Getting Started 5: Controllers

Getting Started 5: Controllers

Controllers are the center of logic in Flitter. Routes should use controller methods to handle requests, and the controller methods should do all of the actual logic to process said requests. Controllers are defined in the app/controllers/ directory, and are made available globally via the _flitter.controller() function.

Creating Controllers

Controllers are defined in the app/controllers/ directory and have the .controller.js extension. Controller names are parsed from the file names and follow the standard Flitter convention for sub-directory naming. Controller classes are just normal classes with methods that take the Express request and response objects and should send a response back. Here's an example controller file:

// app/controllers/Home.controller.js
class Home {
    welcome(req, res){
        return view(res, 'welcome')
    }
    error(req, res){
        const error_string = "Uh, oh! Error."
        return res.send(error_string)
    }
}

module.exports = Home

Controller classes are allowed to contain whatever methods or class variables that you want. However, methods that will be used as handlers for routes should accept the Express request and response objects as arguments and should send a response at some point, then return the status of that sending to Flitter. The two main ways this can be done are directly, using the response object (see the Express docs) or using the global _flitter.view() function.

New controller files can be created from Flitter's template using the ./flitter command, like so:

./flitter new controller subdirectory:file_name

This command will create the file app/controllers/subdirectory/file_name.controller.js which can be referenced as subdirectory:file_name:

/*
 * file_name Controller
 * -------------------------------------------------------------
 * Put some description here!
 */
class file_name {

    /*
     * Serve the main page.
     */
    main(req, res){

        /*
         * Return the main view.
         * It must be passed the response.
         * View parameters can be passed as an optional third
         * argument to the view() method.
         */
        return _flitter.view(res, 'view_name')
    }
}

module.exports = exports = file_name

Using Controllers

Route files should not contain any actual logic. Instead, they should simply list middleware to be applied to a route, and then reference a method on a controller that should contain the logic for that route. Flitter makes available a global _flitter.controller() function that returns instances of the defined controllers by name. Controller names are based on the file name and follow the Flitter convention for sub-directory naming. Here's an example:

// app/routing/routes/index.routes.js
const index = {
    prefix: '/',
    middleware: [
        _flitter.mw('HomeLogger'),
    ],
    get: {
        '/': [ _flitter.controller('Home').welcome ],
    },
}

module.exports = index

Here, the _flitter.controller('Home') call gets an instance of the controller file app/controllers/Home.controller.js and tells Flitter to use the welcome method to handle the / route. It's important to note that the reference does not call the actual function, but just references the name. Flitter will call the function when it receives a request.

That is, this is wrong: _flitter.controller('Home').welcome()
But this is correct: _flitter.controller('Home').welcome

Next: 6: The ./flitter Command