AngularJS: the beauty of concision

Some of you might remember a Backbone blogging engine I made a while back (here’s the code). It certainly wasn’t the most advanced use case for Backbone, but I think that it did a decent job of elucidating some of Backbone’s features: event-driven responsiveness, templating, collections, and so on. It was also a great learning experience and my first foray into thick client-style development.

But then a few weeks ago, a number of trusted friends and colleagues began raving about AngularJS. Curious about what the fuss was about, I began doing some exploring, looking at sample apps, reading the API docs, and watching a few videos, and it became abundantly clear that Angular is an almost shockingly powerful library. I was surprised by the kinds of heavy lifting that can be accomplished with little effort. And so I set out to see how concisely I could re-implement my Backbone project in Angular.

I was quite pleased with the result.

Getting started

The first thing you need to do is specify within your <html> tag itself–I know, crazy, right?–that your HTML page is going to be staging an Angular app. Instead of the typical <html> tag, you need to insert a <html ng-app> tag instead. As you’ll see over the course of this tutorial, you’ll be embedding a surprising amount of basic application logic in HTML tags themselves when you’re using Angular.

Now, I need to specify my document head:

<head>
  <title>AngularJS Blog Engine</title>
  <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.3/angular.min.js"></script>
  <script src="http://stevenlevithan.com/assets/misc/date.format.js"></script>
  <script src="blog.js"></script>
  <link rel="stylesheet" href="style.css">
</head>

Notice that AngularJS has zero dependencies (not even jQuery or Underscore), which is pretty impressive in itself. I’ll also be importing the DateFormat library for making the timestamps on my blog posts look nice. The blog.js file will harbor my application logic.

Setting up a controller

When I was putting together my Backbone blog engine, I didn’t have anything resembling a controller. That was okay because all of my controller-style logic was placed elsewhere, namely in my views, models, and overarching collection. Like Backbone, Angular doesn’t force you to specify a controller, but there are cases where I would highly recommend implementing one. In my case, I have a well-specified resource (blog posts) that have methods attached, which makes a controller a very nice thing to have.

Here’s what my controller (in my blog.js file) looks like:

function BlogController($scope) {
  $scope.posts = [];
  $scope.addPost = function() {
    var now = new Date();
    var time = dateFormat(now, "dddd, mmmm dS, yyyy, h:MM TT Z");
  $scope.posts.push({ title: $scope.postTitle,
                      content: $scope.postContent,
                      time: time,
                      backgroundColor: $scope.backgroundColor });
  }
}

So, let us take stock of what’s going on here. The most important thing to be aware of is the $scope variable. This variable acts as a kind pub/sub store for everything involving our controller. I will store specific blog posts (as hashes/objects) in this $scope.posts variable. When I add a post new with the addPost() function, I’ll snatch the current time with the var now = new Date(); expression and then push a new post to the (currently empty) $scope.posts array.

Each post will consist of four key/value pairs, specifying a title, content, formatted timestamp, and background color. We’ll see in a minute how those values will be passed into the controller, as that logic will take place in our HTML file.

Wiring our HTML to let the Angular goodness flow through

Like I said before, part of the magic of Angular is that it relies on logic embedded within HTML tags (as in KnockoutJS). One of the things that I love about Angular is that I can attach a controller to a specific DOM element and restrict its scope to that element alone. I’ll do that by inserting a <div ng-controller="BlogController"> tag into my document. Everything I do in this tutorial will transpire within that div element, although an app could easily have multiple controllers attached to their own respective DOM elements. Angular is built for this.

Within my new div element, hotwired to sync up with my BlogController, I’ll start with an unordered list for displaying my posts:

<ul>
  <li style="background-color: {{ post.backgroundColor }};" ng-repeat="post in posts">
    <h2>{{ post.title }}</h2>
    <p>{{ post.content }}>/p>
    <p>{{ post.time }}</p>
  </li>
</ul>

The ng-repeat="post in posts" in the <li> tag means that a new list item will be produced for every post in the posts array within my controller. The background color, title, content, and time will be inserted into this template automatically. There is simply no way to do this so concisely in Backbone, where you would need to hook up each post view to a template in your HTML file and then pass it into a collection that is then rendered (correct me in the comments if I’m wrong!).

For good measure, I also want to display how many posts have been made to the blog thus far. This can also be done incredibly neatly:

<h5>Total posts: <strong>{{ posts.length }}</strong></h5>

This kind of syntax should be familiar to anyone who has used Mustache. The most important thing to remember here is that if we placed this <h5> tag outside of the div element tied to our Angular controller, the {{ posts.length }} variable would come up empty-handed. It simply wouldn’t know where to look for this value.

Time to input some data and close the loop

So far, we can’t do much because we can’t input data. Our posts array is empty and there’s not much we can do about that. So let’s create a form and get to work:

<form ng-submit="addPost()">
  <input type="text" ng-model="postTitle" placeholder="Post title"><br />
  <input type="text" ng-model="postContent" placeholder="Post content">
  <select ng-model="backgroundColor">
    <option value="teal">Teal</option>
    <option value="beige">Beige</option>
    <option value="white">White</option>
  </select>
  <input type="submit" value="Submit post">
</form>

The ng-submit="addPost()" embedded in the <form> tag specifies that the addPost() function from our BlogController will be fired upon commit. Remember from our controller that the values for new posts are tied to variables in our div. When we insert an ng-model snippet into an HTML element, that ties the input value to our $scope variable and allows that input to be passed through our controller. I find this to be a much more elegant way of doing things than the standard jQuery $('#element').val(), which is required in Backbone and other libraries.

And that’s it. Everything that was on offer in my Backbone blog engine is on offer here, and all of it implemented in shockingly few lines of code. I invite you to have a look at how I did it in Backbone (have a look in particular at the blog.js file…it’s not pretty).

Thoughts about Angular and Backbone

As much as I still like Backbone and think that it was a crucial stepping stone toward other libraries, I can’t help but think that its days in the sun might soon come to an end. If the maintainers of Backbone can’t find a way to make client-side code this concise, then we might be looking at a gradual sea change in the direction of frameworks like AngularJS.

If this sounds like an overly bold statement, Dear Reader, please do not be bashful in the comments!

Share this post
Facebook Twitter Google
Try AppFog: The new PaaS Hackers love
  • http://dewmap.com/ Brett Coffin

    I have been developing AngularJS apps for over a year now and these examples are numerous, the funniest one i’ve seen is the Todo list on the YUI site, compare to the AngularJS one ;)

    • http://twitter.com/lucperkins Luc Perkins

      Well, the YUI example is a lot more involved than the AngularJS example, but that being said, I see your point :)

  • http://captaincalliope.net/ Captain Lyre Calliope

    From what I understand, the development flow Angular enables is essentially a preview of what web development overall is going to be like once Web Components lands.. which is frankly rather exciting.

    • http://twitter.com/lucperkins Luc Perkins

      Let’s hope cross-browser compatibility doesn’t hold up that particular development!

      • Nicolas Embleton

        Luckily polymer.js is here to feel the gap. That’s exactly its mission. Give WebComponents compatibility and switch whenever the browsers are ready. Awesome article, and totally agree that the modern frameworks are going to make our lives so much easier. I can dream of a building process for a solid web application just like Yeoman’s enabling for the masses already (they have good support for Angular btw).

  • http://www.twitter.com/JeremyCMorgan Jeremy Morgan

    Thanks for posting this! It seems like much of the cutting edge new stuff I’m finding these days is from the appfog feed.

    I watched the video, and I agree it’s very clean and slick. I will definitely be finding ways to implement this in the coming weeks.

    This is definitely where web development is headed. It’s exciting because web apps are getting to be more like actual programs instead of documents with macros, and also the focus lately seems to be taking the programmer away from the “boring” stuff like creating forms, managing events, etc. Bootstrap is a huge part of that as well. Instead of focusing on the same boring tasks they’re done quickly so you have more time to build the cool stuff and make your apps actually do something. It’s so exciting!

    Can you imagine how long it would have taken to build this same app in the video 5 years ago? How about 10 years ago? It’s awesome stuff.

    • http://twitter.com/lucperkins Luc Perkins

      Oh, God. Please don’t make me think about what this would have required 5 years ago. Even worse: think about pre-jQuery. getElementById FTW!!!

  • http://twitter.com/scott_sword Scott Sword

    I can totally relate to this article and I’ve considered writing a post about the exact same thing. About a year ago I was totally on the Backbone train, went through all the docs, became familiar with the framework and ended up building a web app with it for one of my company’s brands. I really liked the way code was organized in Backbone, but when it was all said and done I did a lot more leg work taking care of little UI things that Backbone doesn’t really cover.

    Shortly after that I read a post by a flex developer transitioning to a full javascript stack. It was a great post, I wish I had the link handy, anyway he recommended Angular. Afterwards I looked into it and instantly fell in love. It was everything that I wanted Backbone to be. Just to call out one example is how Angular handles routing. In one line I could easily name my route, define what controller to use, and which template to load. One line! Compared to Backbone, which does still provide good routing, I still needed to write my own template loading script. I mean really–I’m sure Backbone pros will state there are better ways–by the end I had really built a jQuery app organized in Backbone.

    So in the end my conclusion was this:
    If you’re a developer that wants to create a web app from scratch, because you like things to be a certain way, I would implore you to use Backbone. It’s a great way to give your app organization while still maintaining control over a lot of the particulars.

    If you want something that is more strict (strict in a good way) and all-inclusive out of the box go with Angular. Whether I need to build a quick prototype or a more robust web app Angular gets the job done quick and easy. Its really pretty amazing how much work you can get accomplished in one day with Angular. With official support from Google and the amazing community (not to mention the Angular-UI project on Github) Angular is only going to get better.

    • http://twitter.com/lucperkins Luc Perkins

      Thanks a lot for weighing in! I, too, am quite smitten with it. Like you, I’m glad that I had the experience of using Backbone precisely because things have to be specified on such a granular level, which helped me understand the mechanics of jQuery, Underscore, etc. a lot better. But at the end of the day, Angular is just an absolute Corvette when it comes to development time :)

  • http://twitter.com/Dj3bbZ Khalid Jebbari

    I played with both Backbone and Angular. You’re comparing a full fledged framework (Angular) and a library of MVC components (Backbone). Angular is made for CRUD-like apps. Backbone lets you do (almost) any kind of app. Both have a role to play, but by no mean Angular may replace Backbone.

    I couldn’t find the code for the Angular version of the blog engine on your Github, but if the full code is what you published in the article, please realize that you pulled in 487KB (!) of code for something that simple – latest angular 1.0.4 is 487Kb uncompressed, 82KB minified : way more than Bacbone + Chaplin/Marionette (meta frameworks on top of Backbone that play at the same level than Angular) + jQuery + Underscore…

    • Ignat

      The argument about the size is pointless. I would recommend you to read Backbonejs vs Angularjs : Demystifying the myths. Also keep in mind that AngularJS is available on Google’s CDN, which means that probably it’ll be loaded much faster than a bunch of smaller files from your hosting…

      • http://twitter.com/Dj3bbZ Khalid Jebbari

        Just read it, and it confirms what I’m thinking. Backbone and Angular are not comparable. Remember, the right tool for the right job. Minimal and flexible versus monolithic and powerful. And when I read “[...] Angular is a better choice in all scenario’s where you would use Backbone”, I stopped considering the author as knowledgeable enough.

        –Edit : also, a CDN is not always your best bet, there are also efficient ways to manage assets caching by yourself.

        • ganaraj p r

          Interesting. I havent yet found a single opinion from anyone claiming to refute this statement “[...] Angular is a better choice in all scenario’s where you would use Backbone”… I would invite you to provide me an example scenario where Backbone suits the scenario much better than angular. My argument still stays the same, “On the client side, Angular is a better choice in all scenario’s where you would use Backbone” and I will stick with it until someone provides me with a scenario where it is not.

          On another note just to show you some examples of where Angular is used and its not just for CRUD apps. http://www.bombermine.com is one example. The game’s interface was built with angular. Another example is Awesome New Tab Page extension for chrome. Also my first app in Angular was kind of a photoshop like graphical editor written all in HTML5. None of the 3 examples are CRUD apps.. ( Backbone is fine in these scenario’s too actually, but Angular seems a better choice because of its ability to write re-useable components. ).

          On the other hand Backbone does seem like something that perfectly suits a cookie-cutter REST backend. If the backend does define all the HTTP verbs and treats each as a resource then Backbone works fine ( because then the model sync is easy.. ). On the other hand if for some reason your GET is for a particular url and POST is to another then implementing that in Backbone seems like a hack ( to me atleast! ).

          • http://twitter.com/Dj3bbZ Khalid Jebbari

            Well, the CRUD mention is not from me, it’s from Angular’s authors themselves. Don’t remember when/where I read it, maybe when I met the Angular core team at dotJS (Paris, France, November 2012).

            What’s good with Backbone is that it makes you a better developper, because it’s low level and forces you to think to about an architecture application. Angular provides it out of the box, which is what we expect from a fully fledged framework, but makes you an Angular developer. Not necessarily a bad thing, especially when you want to build something fast.

            And Backbone can help you reduce code amount by reusing parts of it (especially models) in both Node and the browser. AirB’n'b has even released a framework based on backbone where you write the code once and it works both on client and server side, and fallback to regular rendering by the server if browser doesn’t have Javascript activated (https://github.com/airbnb/rendr). Un-possible with Angular.

            Don’t get me wrong. Angular has lot of nice things, declarative UI is cool, necessary code amount is very nice and lets you focus on application code. With Backbone you could decide to use only the Model/Collection, or only the Router, or both. You’re free. And there are fully fledged frameworks based on Backbone : Chaplin, Marionnette, Thorax, Aura amongst others. Remember, the right tool for the right job. If Angular fits your need, stick with it.

      • http://twitter.com/JoshGlazebrook Josh Glazebrook

        Using Google’s CDN isn’t necessarily for transferring an asset to a user faster. It’s more as a way of providing a remote asset that may already have been loaded by another website thus the browser already has it cached and doesn’t need to fetch it again.

  • Karl

    Took another stab at the backbone.js version (with working edit view) here: https://gist.github.com/4618724, though i have to admit that the angular version you describe is way slicker than that :)

    • http://twitter.com/lucperkins Luc Perkins

      Your Backbone technique is clearly more advanced than my own :) Good call using Require as well (I still need to work on my Require skills). I have a lot to learn from this example. Thank you so much for your time and effort! You rule!

      But yeah, there is something to be said for Angular nonetheless ;)

  • http://profiles.google.com/luismgz Luis Gonzalez

    Thank you very much for this post!
    It cleared up a lot of stuff for me.

  • http://www.patibs.nl/ Ebrahim Patel

    Nice article Luc. Yes working with views in AngularJS is very simple comparing to backbone where you have to roll up your sleeves. I recommend developers start working with AngularJS for the very reasons. If you are going to support IE7 and IE8 then please feel free to use backboneJS.

  • Jon

    Nice, thank you for the clear, simple and straightforward tutorial.

  • xiaoying

    you don’t even need dateFormat! angular has a built in date filter :)

  • http://rommelxcastro.com/ Rommel Castro A.

    i been working with Backbone for around a year, yesterday i started my first project with AngularJS, i fell in love with it, the only thing i hate it’s it docs, are useless

  • tushar sharma

    Hey, I need help.

    I am working with SQL Server 2008, MVC.NET 4.0 and EF4.0 for a Single Page Application.

    I have a form that has multiple dropdownlists (say 5).

    The dropdown gets populated using LINQ query from the database. It returns the list as “items”

    Now in the Front-end I am populating the values in the dropdownlists using ng-model=”item.projectId”

    Now
    when I submit the form, its quite obvious that the projectId will be
    posted to the server due to the double-binding nature of ng-model
    directive.

    I want to get the selected (user selects while filling up the form) values collectively (possibly into an array ) and send it to the controller.cs file where there an array to consume those values and store that in the table. Can anybody give me tips on this?

    I am new to this!

Powered by Olark