Guiding The Geek In You
Building an AngularJS application using partial views and supported by a Node.js / ExpressJS back-end is doable with a little effort.
Two methods exist for creating modules in AngularJS. I prefer the setter method. Note below we are injecting dependencies on our external controller and ngRoute. Both of these items source from external JS files, so don’t forget to attach them within your index.html.
angular.module('myApp', [ 'ngRoute', 'myApp.controllers' ]).
Pro Tip: Ensure the angular.js version matches angular-route.js! Download them both at the same time from code.angularjs.org.
$locationProvider allows access to .html5mode(), a piece of Angular magic that ensures URLs look like regular URLs in modern browsers, and hash-bangs in older ones. Neat trick! Keep these two caveats in mind when configuring a Node.js / ExpressJS installation:
config(function ($routeProvider, $locationProvider) { $routeProvider. when('/', { templateUrl: 'partials/home', controller: 'HomeController' }). when('/pizza', { template: 'I Love Pizza!' }). otherwise({ redirectTo: '/' }); $locationProvider.html5Mode(true); });
Standard configuration from the Angular perspective thus far. The controller is also super basic – just stubbed out for later use:
angular.module('myApp.controllers', []). controller('HomeController', function ($scope) { });
Configuring Node.js correctly (via the ExpressJS framework) is tricky. However, thanks to btford’s excellent seed project (available on github) I refined this:
var express = require('express'), routes = require('./routes'), http = require('http'), path = require('path'); var app = module.exports = express(); app.engine('html', require('ejs').renderFile); app.set('port', process.env.PORT || 3000); app.set('views', __dirname + '/views'); app.set('view engine', 'html'); app.use(express.logger('dev')); app.use(express.static(path.join(__dirname, 'public'))); app.use(app.router); if (app.get('env') === 'development') { app.use(express.errorHandler()); }
Pro Tip: Make sure this line:
app.use(express.static(path.join(__dirname, 'public')));
comes before this line:
app.use(app.router);
Order matters! We need Node.js to serve the static page request before passing the request to a route handler. This way AngularJS $routeProvider works as it should.
app.get('/', routes.index); app.get('/partials/:name', routes.partials); app.get('*', routes.index);
The code above is the connective tissue between AngularJS and Node.js. First, note the references to routes.index. They point to index.js, the JS file containing the specific routing information about the three potential GETS. The first and third lines will route all traffic to the index page, and line two routes requests to the partials directory (rendering any partials found within). Line three in particular is important, as this catch-all is vital for enabling html5mode in our AngularJS configuration.
Index.js:
exports.index = function(req, res){ res.render('index'); }; exports.partials = function (req, res) { var name = req.params.name; res.render('partials/' + name); };
And finally, to kick off our Node.js server:
http.createServer(app).listen(app.get('port'), function () { console.log('Server listening on port ' + app.get('port')); });
The entire Node.js configuration file:
/********************* * Module dependencies *********************/ var express = require('express'), routes = require('./routes'), http = require('http'), path = require('path'); var app = module.exports = express(); app.engine('html', require('ejs').renderFile); /*************** * Configuration ***************/ // all environments app.set('port', process.env.PORT || 3000); app.set('views', __dirname + '/views'); app.set('view engine', 'html'); app.use(express.logger('dev')); app.use(express.static(path.join(__dirname, 'public'))); app.use(app.router); // development only if (app.get('env') === 'development') { app.use(express.errorHandler()); } /******** * Routes ********/ // serve index and view partials app.get('/', routes.index); app.get('/partials/:name', routes.partials); // redirect all others to the index (HTML5 history) app.get('*', routes.index); /************** * Start Server **************/ http.createServer(app).listen(app.get('port'), function () { console.log('Server listening on port ' + app.get('port')); });
Awesome, an environment which supports AngularJS, runs Node.js / ExpressJS! All that’s missing now is the View.
If you are like me you prefer your HTML as pure as the driven snow. By default Express does not make this possible, as it requires the use of Jade, an HTML Template technology. Fortunately, Embedded JavaScript (ejs) is an easy replacement for Jade, affording us the luxury of a powerful framework and clean markup. Download and install ejs as you would any other node plug-in:
npm install ejs
That’s all folks. Comments, questions? I would love to hear from you. Don’t be shy, and…
Thanks for reading!
Happy New Year! It has been a few weeks since my last post. My sabbatical was refreshing and productive. I finished my first major AngularJS project, which I am excited to start writing about, and of course took some much-needed down time. I hope your end of year festivities were equally pleasant.
This year I have a diverse topic list in store for CompassInHand that I hope will be as interesting to you as it is educational to me. Technology is amazing. There is no end to what can be learned. My hope is that I can give back some of what others are teaching me.
As mentioned, I released my first application written purely in the “Angular way”: Our XBOX 360 Library (OX360L)! If you are interested in checking out the code, please visit the project git repo.
Loyal readers will note: prior to my holiday sabbatical my posting interval was about once per week. Unfortunately I rarely had enough time to do the research, understand the technology, and write a quality post about it within the single week. Therefore my new posting interval will be about twice per month. The additional week will be a tremendous help and should make for tighter posts with more code examples.
While no release date exists yet, this year you can expect CompassInHand to undergo a big face lift. With the help of my good friend (and new father!) Trian Koutoufaris a new WordPress theme is slowly taking shape – including an actual site logo! Stay tuned.
Finally, I plan to begin supporting RSS feeds. This is not a big technical challenge, just an administrative oversight I never considered before. Whether this feature is useful will be up to you guys – please, comment and let me know!
Lots of things!
Over the next several posts I will be discussing some of the many (many, many) lessons I learned while building OX360L. Some of these lesson topics may include:
Looking past Angular / OXB360L, other post topics coming in the next several months will include:
Finally, I have another project getting ready to spin up. Look for hints and mentions as meaningful progress is made. Hopefully it can be useful for all of you who go to lunch with coworkers.
Thanks for reading!
A few nights ago over coffee at the local Starbucks I enjoyed one of those moments we as web developers secretly love: a full throttle conversation about ideal, multi-tiered web applications. As we broke down tiers and discussed their relationships, we considered different scenarios: what if the user is on a mobile device? What if their connection speed sucks? What if the site they are using has a million controls?
In fact, what if the website looked and needed to behave like a regular application? Would a massive collection of ad hoc jQuery event handlers, Ajax calls / RESTful services and finely crafted HTML be enough? Maybe. But a better solution exists. Enter the framework.
A framework is a specialized type of library. For programming languages, a library is a collection of behaviors (think: functionality) written in terms of the language, that can be called by using a well-defined interface. Libraries are meant to be used by multiple programs or in multiple areas of a single program, largely because they encapsulate commonly used functionality set apart from the program’s actual code. This makes writing complicated code somewhat easier, as repetitive / complex chores have already been solved and are only a friendly method call away.
A library is passive. Developers must write their code using that library’s interface to get anything out of it. Thus an entire program can be written never using a library’s treasure trove of functionality, even if available the whole time. Not so with frameworks.
Like the libraries from whence they came (poetically anyway), frameworks are a collection of functionality written in terms of the language they support. Frameworks are portable, meaning they too can be reused in multiple projects written in their given language. However, unlike a library, frameworks are bossy. Using a framework correctly means subscribing to how the framework developers view application organization and development. Let that sink in for a moment. Within a framework, your program no longer directs traffic. The framework becomes the traffic cop, and your program the exotic sports car (or three row SUV, which ever you prefer).
Frameworks share four attributes that set them apart from libraries. Where libraries are accessed as needed, frameworks work on the Hollywood Principle, aka “Don’t call us, we’ll call you.” The framework takes care of business and calls your program when it’s show time. The fancy term for this behavior is inversion of control. Second, a framework must have a default behavior, meaning once installed and properly configured, it has to do something useful right out of the box (typically a “hello world”). Next, they must afford some way for developers to extend their functionality, either by overriding default behavior or by creating new behavior within the internal guidelines. Finally, framework internals are considered off-limits. Extend all you want, look under the hood, show it off to your friends, but don’t touch anything inside. Modify the magic and you void the warranty.
During my research I looked at many languages. Each of these languages had at least one framework written for them. So, while a statement like “all languages have frameworks” would probably get me in trouble, I think it is safe to say frameworks have benefits that are tough to ignore, no matter the language. Here are a few popular languages and their corresponding web frameworks:
PHP: CodeIgniter, Zend
Ruby: Padrino, Rails, Sinatra
Java: Grails, Play
Python: Django, Zope2
JavaScript: AngularJS, Ember.js, Backbone
Node.js: Express, geddy, Meteor
In fact, frameworks are so helpful they are even used in CSS. Examples include:
Bootstrap
Foundation 3
Skeleton
Frameworks are not for everybody. Some are better than others in any given situation. Frameworks can have tough learning curves, particularly for the novice developer. The unusual usage demands and seemingly arbitrary control flow may seem senseless until well understood. Framework use can also lead to code bloat by adding unnecessary functionality and inspiring work arounds written by developers unfamiliar with the framework’s complexity. Speaking of complexity, take a look under the covers and marvel at the magic. Pre-implementation study and research is sincerely recommended!
These are real concerns you should absolutely consider. However, frameworks also bring a feast to the table. As well-tested and typically open source application scaffolding, frameworks can help separate concerns in extremely reliable ways, decreasing code spaghetti. In fact code quality is often amplified when developers follow usage rules and color inside the lines. Although structured, frameworks are extensible when necessary – while still cutting development time by taking care of common tasks (just like any other library). Finally, over the long-term the framework becomes invisible, improving project delivery time and code reusability.
Thanks for reading, and happy frameworking!
Installing nodejs on Mint or Ubuntu is generally a smooth process. Nothing that will bend or break your mind – if you start with a clean slate – and assuming a recent build of Mint or Ubuntu!
Note for the paranoid like me: for the fresh install, we are going to add an “untrusted” PPA (personal package archive). Untrusted simply means that these archives are not overseen by the community at large, so using software from these resources could potentially break your system.
That said, I have used nodejs from Chris Lea’s PPA for months now with zero problems – he does a fantastic job!
Nodejs-dev and npm are included in the nodejs package as of v0.10.0 – another reason to use Chris Lea’s PPA.
Because the latest version of nodejs (or nodejs-dev or the npm) is not available in the default repo, remove any traces before you begin:
sudo apt-get remove nodejs nodejs-dev npm
Install the latest version of nodejs package:
sudo apt-get update
sudo apt-get install python-software-properties python g++ make
sudo add-apt-repository ppa:chris-lea/node.js
sudo apt-get update
sudo apt-get install nodejs
Check that nodejs version v0.10.20 (or better) installed correctly:
nodejs -v
Go ahead and check NPM as well (v1.3.11 or better):
npm -v
Thanks for reading!