Sample Application with Angular.js

After I blogged a three-part Backbone.js tutorial (part 1, part 2, part 3), a number of people asked me to try Angular.js. So I decided to take it for a test drive. I thought it would be interesting to rebuild with Angular.js the Wine Cellar application I had built with Backbone.

If you are new to my Wine Cellar application, it is a simple CRUD app that allows you to manage (create, update, delete) wines in a Wine Cellar. The data is stored in a MySQL database that the client application accesses through a simple RESTful API. This seemed to be a good fit since CRUD applications are often positioned as the sweet spot for Angular.js.

You can run the application here. The UI is intentionally plain to keep the focus on the key learning points. For obvious reasons, this online version is “read-only”. You can download the fully enabled version here.

Application Walkthrough

The best way to get started with Angular.js is to go through the excellent tutorial that is part of the documentation, so I’ll only provide a high level overview of my code here.

Like the Backbone.js implementation, the Angular.js version is a deep-linkable single page application. index.html is defined as follows:

<!DOCTYPE HTML>
<html xmlns:ng="http://angularjs.org">
<head>
<title>Angular Cellar</title>
<link rel="stylesheet" href="css/styles.css" />
</head>

<body ng:controller="RouteCtrl">

<div id="header">
    Angular Cellar
    <button ng:click="addWine()">New Wine</button>
</div>

<div id="sidebar">
    <ng:include src="'tpl/wine-list.html'"></ng:include>
</div>

<div id="content">
    <ng:view></ng:view>
</div>

<script src="lib/angular-0.9.19.min.js" ng:autobind></script>
<script src="js/services.js"></script>
<script src="js/controllers.js"></script>

</body>

</html>

The application is driven by a set of Controllers that I defined in controllers.js as follows:

function RouteCtrl($route) {

    var self = this;

    $route.when('/wines', {template:'tpl/welcome.html'});

    $route.when('/wines/:wineId', {template:'tpl/wine-details.html', controller:WineDetailCtrl});

    $route.otherwise({redirectTo:'/wines'});

    $route.onChange(function () {
        self.params = $route.current.params;
    });

    $route.parent(this);

    this.addWine = function () {
        window.location = "#/wines/add";
    };

}

function WineListCtrl(Wine) {

    this.wines = Wine.query();

}

function WineDetailCtrl(Wine) {

    this.wine = Wine.get({wineId:this.params.wineId});


    this.saveWine = function () {
        if (this.wine.id > 0)
            this.wine.$update({wineId:this.wine.id});
        else
            this.wine.$save();
        window.location = "#/wines";
    }

    this.deleteWine = function () {
        this.wine.$delete({wineId:this.wine.id}, function() {
            alert('Wine ' + wine.name + ' deleted')
            window.location = "#/wines";
        });
    }

}

RouteCtrl defines the routes of the application. Each route is defined by a template that is rendered in <ng:view> inside index.html. There can only be one <ng:view> in a document (more on that later). For example, here is the wine-list.html template:

<ul ng:controller="WineListCtrl">
    <li ng:repeat="wine in wines">
        <a href='#/wines/{{ wine.id }}'>{{ wine.name }}</a>
    </li>
</ul>

The WineListCtrl and WineDetailCtrl controllers provide access to the data using a service defined in services.js as follows:

angular.service('Wine', function ($resource) {
    return $resource('api/wines/:wineId', {}, {
        update: {method:'PUT'}
    });
});

Services provide a great way to abstract your data access logic, and to easily change it without impacting the rest of the application. For example, you could easily change the Wine service to use a Mock service instead of a RESTful service.

Impressions

I was able to build this application in a very limited amount of time with no prior knowledge of the framework. The data-binding implementation is nice, and, in general, the amount of boilerplate code you have to write is very limited. Frameworks are often a matter of style and personal preferences. Angular.js takes a more declarative approach than other frameworks. Based on this initial experience, I would also describe it as more prescriptive: I didn’t have to spend a lot of time wondering what was the best way to do things as Angular.js tends to have clear utilization patterns. I haven’t spend enough time with the framework to determine if that comes at the cost of less control, and I’d love to hear what other people are thinking.

The only problem I ran into while building the application is the “one route / one view” coupling I alluded to above. As suggested in this thread, you can use <ng:include> to bind partials in the page. The same thread also indicates that multiple <ng:views> per route definition will be supported in the future. I was able to handle the simple UI requirements of this app using one <ng:view> and one <ng:include>. For more complex applications, I’d love the routing infrastructure to allow me to easily and arbitrarily add, remove, change, or animate different elements of the DOM when the route changes in order to support deeper UI transformations. I’m sure there are ways to do this. If Angular.js folks are reading this post, I’d love to hear what they think and what’s coming.

Download

The application is available on GitHub here.

You will need the RESTful services to run this application. A PHP version (using the Slim framework) is available as part of the download. If you want to test the application with a Java back-end, you can download the Backbone version here, and reuse its JAX-RS back-end.

67 Responses to Sample Application with Angular.js

  1. Thomas Burleson February 3, 2012 at 4:30 pm #

    Hey Christophe,
    Thanks for your example above. Check out my sample `CafeTownsend with AngularJS & CoffeeScript`:

    https://github.com/ThomasBurleson/angularJS-CafeTownsend
    http://thomasburleson.github.com/cafetownsend/index.html#/login

    And I agree with your summary… IMHO, AngularJS has a big area that must addressed after the v1.0 release: routing and page flows/transitions. Meanwhile, it is a amazing IoC framework that promotes MVVM architectures and reminds Flex developers of Swiz.

  2. Thomas Burleson February 3, 2012 at 5:43 pm #

    Christophe,
    Readers should note that your application uses a .9 version of AngularJS. FWIW, the v0.10.6 version(s) and higher have changed significantly in how developers configure services with DI.

  3. Eric Pesser February 6, 2012 at 11:00 pm #

    Hi,

    I’m looking for a MVC/MVVM library… What’s the best for you? Backbone? Angular? Knockout?

    It seems that all of these libraries are quickly evolute so I fear a little bit to choose one of them and get some regrets in the close future!

    Bye and thanks for your wonderful articles!

    • Christophe February 9, 2012 at 8:52 pm #

      Hi Eric,
      As I mention in the article, frameworks are often a matter of style and personal preferences. There are many vectors to consider: declarative vs programmatic, prescriptive vs non-prescriptive, full-stack frameworks vs micro-frameworks, close to the DOM vs total DOM abstraction, etc. It’s not a one size fits all situation: it depends on your own preferences and the type of app you are building.

  4. Marlus Araujo March 9, 2012 at 4:09 am #

    Hi Christophe, nice example.
    I’ve notice that after this post you just talked about Backbone.js.
    I’m learning both of the frameworks, but something is telling me that Angular.js is very promissing… it’s very easy to create an organized app, and very fast. The concept is also very clear.
    I’m just curious about your opinion, I will keep reading your blog.
    cheers!

  5. Stanley April 7, 2012 at 4:59 pm #

    Really thanks for tutorials with Angular and also backbone I just started with js frameworks and I learned a lot.

  6. alex May 10, 2012 at 4:03 pm #

    It flickers with curly braces bindings in IE.
    Should there be a ng-cloak directive set? http://docs.angularjs.org/api/angular.module.ng.$compileProvider.directive.ngCloak

  7. Marty Pitt May 16, 2012 at 12:40 am #

    Awesome – thanks for the tutorial.

    As you say, frameworks are a matter of taste. As a Flex user making the transition to a JS world, I find AngularJs to be the closest match to my dev style.

    Thanks for bringing it to my attention!

  8. Alfredo Ramirez August 16, 2012 at 7:31 am #

    Hi Christophe, wonder if you’re available for some questions about this tutorial code? Please? There are some pieces I just don’t follow.

    Thank you!!

  9. Allan Oliveira August 18, 2012 at 1:54 pm #

    Nice post. Answered a couple of questions I had in mind as like you I’m new to Angular JS and still accessing if I should keep going with it or stick with KnockOut JS which I’ve had more experience with and I’m a bit more comfortable with. Angular JS seems more powerful and a very beautiful framework that makes me feel like I’m actually making an ASP MVC application (routes, DI, Services, etc.). I’m trying to use it with PhoneGap so I need to figure out how I can use both libraries together in a nice way (PhoneGap seems to use a lot of event listeners with success/fail callbacks so I’m trying to integrate these properly).

  10. nilay August 26, 2012 at 3:07 pm #

    I try to compile the angular js with the phone in android. And I am compiling using ant(ant debug).
    In the index.html file of phonegap application:

    Google Phone Gallery

    Wonderful Coupons

    {{coupon.snippet}}

    and in the controllers.js file:

    /* Controllers */
    function CouponListCtrl($scope) {
    $scope.coupons = [
    {“name”: “coupon1″,
    “snippet”: “Wonderful car at a magical discount “,
    “imgUrl”:”assets/www/images/img1.jpg”},
    {“name”: “coupon2″,
    “snippet”: “Buy a bucket to gain a sachet”,
    “imgUrl”:”assets/www/images/img2.jpg”},
    {“name”: “coupon3″,
    “snippet”: “Buy a dinner to gain a chiner”,
    “imgUrl”:”assets/www/images/img3.jpg”}
    ];
    };

    But when I compile using ant debug and load the applicaition using adb install bin/.apk I get the
    {{coupon.imgUrl}} and {{coupon.snippet}}

    Why does the angular functionality not kick in ?

    So basically how did you integrate in terms location of the js libraries for compilation using ant. …(I am using command line compilation…)

    thanks for any help…

  11. Lee Chee Keong August 30, 2012 at 2:57 pm #

    I liked your demo very much but I work mainly in Grails. So I thought I give it a go to port it to Grails and make it work with the latest AngularJS libraries 1.0.1. I have uploaded the sample into github:

    https://github.com/leecheekeong/grails-angular-cellar

    Hope you find it interesting

  12. Narretz October 2, 2012 at 6:31 pm #

    I also updated the app to Angular 1.0.2, but I kept the Slim.php API.

    https://github.com/Narretz/angular-cellar

    There are also some smaller new features.

    • Tiziano November 10, 2012 at 8:45 am #

      @Narretz thanks it’s nice to see how it all change in 1.0.2, however I can’t get to save a new wine in the cellar. I’ve tried a few changes but I really don’t get what’s wrong… In the firebug console I see: SyntaxError: Unexpected token S. Any clue?

  13. Mark October 5, 2012 at 4:23 pm #

    I updated to 1.02 as well. I added a Python restful backend and tests, too:
    http://github.com/markfink/ajaxdemo

    I am going to present the ajaxdemo at PyCon DE in October. I hope that is ok for you.

    All the best,
    Mark

  14. Sneha October 11, 2012 at 6:53 am #

    Hey it sneha im totally new to grails and want to allow the user from database to login from the page. i ahve created the registration table and also have registered user in it. and now want these user form database to login to their profile page. i am not able to get the code for it all i have got i the plugins .. but they dont seem to work out for me…. please help… !!1Thanks in Advance!!! or if you know any blogs which i can refer then lease suggest!!!

  15. Gilvam November 12, 2012 at 9:40 am #

    What I do when this error appears:
    ERROR: XHR: api/wines Object {method=”GET”, url=”api/wines”, …} Object {status=404, …}

    • Jim January 21, 2014 at 11:10 pm #

      Ever figure this out? I’m having the same issue.

    • Jim January 22, 2014 at 12:30 am #

      Figured it out. The issue was with the Slim routing. It was an Apache config. You need to change “AllowOverride None” to “AllowOverride All” in order for the Slim.php routing to work correctly.

  16. Bob Dole November 21, 2012 at 1:14 am #

    Can you try this example app + writeup with Ember.js? (Be sure to remove all deadly weaponry from your house before doing so or you might kill yourself during.)

  17. discount coby ledtv3216 32-inch November 23, 2012 at 11:16 pm #

    I am not certain the place you are getting your info, but great topic. I needs to spend some time learning more or understanding more. Thanks for fantastic info I used to be searching for this information for my mission.

  18. lelaki memandang November 24, 2012 at 9:47 am #

    Pretty great post. I just stumbled upon your blog and wished to say that I have really loved surfing around your weblog posts. After all I’ll be subscribing for your rss feed and I hope you write once more very soon!

  19. ESET Smart Security 5 username and password November 27, 2012 at 5:31 am #

    Fantastic website. Lots of useful information here. I’m sending it to some pals ans also sharing in delicious. And naturally, thank you in your effort!

  20. laser targeted list building December 20, 2012 at 8:09 pm #

    This article will assist the internet viewers for setting up
    new web site or even a weblog from start to end.

  21. Chris Lee January 6, 2013 at 3:03 am #

    I bound angular front-end together with node/mongodb back-end, it doesn’t work.

  22. Chandra January 18, 2013 at 3:18 pm #

    With AngularJS, isn’t it tight coupling between the template and your behaviors. Although productive with initial development, it seems more obtrusive and less maintainable, with bindings everywhere in the templates. Not sure if there’s any way around that though.

  23. Rob January 27, 2013 at 4:31 am #

    Hello. I really appreciate the information you’ve provided and the example. I’m struggling with where in the routes Angular ties into something like Passport (Facebook Auth) and how you’d protect certain paths and make sure the user is authenticated. Has anyone dealt with this and could you share the technical details with me please?

    • Rob January 27, 2013 at 4:32 am #

      I’m using passport, express, mongoose, jade and facebook auth

      • Jeff Jones June 29, 2013 at 7:37 pm #

        Hey Rob – is there any good resource online for combining passport + nodecellar?

  24. dilip February 15, 2013 at 2:40 pm #

    Hi,
    Nice one as always.

    We are in the process of migrating a flex application with spring,blazeds in the server.

    Am thinking to employ angularjs as the javascript framework.

    Our concern is regarding the server communication.
    As we can see, Most of the solutions comes in the samples/tutorials are based on REST.
    Could you please suggest me a solution which can protect my backend pojo classes.
    Do we really need to go for a restful approach ?
    Any advice on the performance when comparing with amf? And rest based calls?
    Do I have any alternates like continuing with amf (balzeds) layer or any other json based rpc rather than using rest ?
    Thank you for your time
    Regards,
    Dilip

  25. Chris Lee February 28, 2013 at 8:29 am #

    After save new wine or delete wine, the listview doesn’t change accordingly!

  26. Pharmc7 March 1, 2013 at 5:02 am #

    Hello! fgdfdaf interesting fgdfdaf site! I’m really like it! Very, very fgdfdaf good!

  27. Jochen (eddelplus) March 16, 2013 at 10:26 am #

    Hi Christophe,

    You’ve already supplied PHP/Slim and JAX-RS/Jersey backends for the wine cellar. I’ve recently tried to make Groovlets more RESTful and come up with a GRESTlet approach. My primary sample for that is another wine cellar backend, using Groovy and the H2 database.

    I’ve updated the Angular.js client to the current stable 1.0.5 release. Getting over the 1.x barrier was a bit of a struggle. I’ve preserved the deep linking to individual wines and improved the solution by updating the wine list after any changes.

    Feel free to visit my home page and grab the downloads.

    Cheers, Jochen

  28. Satwati March 23, 2013 at 10:40 am #

    Can you suggest any other way to get data from database other than using RESTful web service??

  29. Robin March 28, 2013 at 12:02 pm #

    Hi,
    I tried the demo application. The create,delete and update calls are not working. It appears that the content type sent by the browser is not json. Could you please suggest a fix for the same ?

  30. Fabio Biondi April 27, 2013 at 8:54 am #

    AngularJS is the best framework I have tried in the latest months.
    It reminds me Flex a lot! I love it and I really suggest to use it.
    10000 lines of code can really become 2000.

    Everything is very easy except when you need to create a custom directives or animate some stuff. In this case the learning curve is more high but it’s just like Flex: very easy to use at the begin but if you need your own custom advanced components you need to delve into topics.

  31. Men Toms Cordones Shoes July 6, 2013 at 5:20 am #

    Alter that shoes into a full-scale Goldmine

  32. 大きい傘 August 25, 2013 at 8:43 pm #

    ペリカン 万年筆 インク

  33. jon smith September 12, 2013 at 4:16 am #

    how can I bind the values of more than one dropdown in array in AngularJS ?

  34. Terence September 13, 2013 at 9:59 pm #

    I blog often and I really thank you for your information.
    This great article has truly peaked my interest.
    I’m going to bookmark your website and keep checking for new
    details about once per week. I subscribed
    to your Feed too.

  35. Ajeesh September 25, 2013 at 11:28 am #

    Hi christophe , been a follower from the backbone examples. Would be interesting to get your viewpoint on durandaljs

  36. sushant November 7, 2013 at 2:09 am #

    Hi Christopher, nice post. you have covered good features of angular js in a simple application. I thoroughly enjoyed and gained valuable knowledge from your hands on post.

    In my quest to learn more about the SPA, I have registered for a webinar on Benefits of developing Single Page Web Applications using AngularJS, it looks a promising one http://j.mp/1a9aK6t

  37. Jimmers November 15, 2013 at 12:19 pm #

    Hi Christophe,

    I downloaded your example Angular Cellar example from the Github repo but get a 403 Forbidden error on “/#/wines’ which causes the loading of the wine list in the DB to fail. I have given the entire project Read and Write access in case it is a permissions issue.

    Any ideas?

    Thanks

  38. Tim November 18, 2013 at 1:42 pm #

    I am just a starting Angular JS programmer, but I have certain things I love about it and some things I hate… It is yet to be seen if one outweighs the other.

    Things I love : Databinding is very nice. Some of the code organization is well done. And there are perks (Like filtering and searches) that come so easy to the framework that they are wonderful.

    Things I hate : Really one thing in particular… basically, Angular JS has taken the MVC framework and applied it to Javascript. Some people grok that setup and love it but I am not in that group – I find it limiting to be honest. I am not sure if this is a fatal problem for the framework but it very well could be – I have a very basic revulsion to the idea that I have to organize my code in certain subdirectories and name things in certain ways for that magic to happen.

    Overall, I am still learning and things may still tip one way or the other. I do wish the documentation was more clear, but that’s to be expected…

  39. Prashanth December 2, 2013 at 2:18 am #

    This has an issue!

  40. Karthik January 3, 2014 at 1:17 am #

    Hello Christophe,

    First of all thanks for the very nice tutorial. Could u please help me out on how to create an Angular app using Angular.js + node.js + mongodb.

  41. Helga Klingelhoets January 4, 2014 at 8:06 am #

    I know this if off topic but I’m looking into starting my own blog and was wondering what all is required to get setup?
    I’m assuming having a blog like yours would cost a pretty penny?

    I’m not very web smart so I’m not 100% sure. Any tips or advice would be
    greatly appreciated. Kudos

  42. Pablo February 5, 2014 at 8:57 am #

    Im using mozilla and yuor demo http://coenraets.org/angular-cellar/#/wines didnt work for me.

  43. Gaurav Madaan March 9, 2014 at 11:36 pm #

    The article is really very nice. Thanks. Can you please post some article on Slim also and how to implement security like while login in RESTFul services

  44. Floy April 12, 2014 at 10:42 pm #

    It also explains partially, why diabetics have high cholesterol, high triglycerides, high blood pressure, glaucoma and
    cataracts, heart disease, low energy, anxiety and obesity.
    Additionally, the second stage is also part of the weight loss process, only it is slower and more
    consistent. Most mothers lose half the weight they gain quickly after giving birth.

  45. Clash of clans hack Guide April 15, 2014 at 11:55 am #

    But this game clash of clans hack mac is that you should understand how
    to spent elixir, gems andd god are 2, 001, 000. Put down a couple random guys.

  46. cleaning carpets london April 17, 2014 at 6:39 am #

    It’s enormous that you are getting thoughts from this post as
    well as from our argument made at this time.

  47. Tessa April 25, 2014 at 10:51 am #

    For the benefit of developing an important product comparisons, we’ve looked at routers in this range that share similar
    characteristics including IEEE 802.11n wi fi standards,
    2.4 GHz band and dual antennas. If you’re buying new router,
    nothing less than an n router is highly recommended.
    It might be wise to upgrade into a wireless n layer 3 switch, in case you possess a wireless
    g router. The newest routers also increase speed with
    wi fi Quality of Service applications (QoS) regular, which makes effective utilization of
    Ethernet connections by prioritizing multimedia visitors according to the application’s sensitivity to delay.
    Many wireless n routers also use multiple-input and multiple-output (MIMO) radio
    antennae to boost speeds.

  48. Karolin April 26, 2014 at 10:41 pm #

    Sometime on Friday evening, one lucky online casino player experienced the thrill
    of victory with a $26,489 jackpot win. The American version has two zeros close to wheel; the european has one zero.

  49. New Balance zapatillas hombre April 28, 2014 at 1:38 am #

    Woah! I’m really loving the template/theme of this site. It’s simple, yet effective.
    A lot of times it’s very hard to get that “perfect balance” between user friendliness and
    visual appearance. I must say that you’ve done a very good job with
    this. Additionally, the blog loads very fast for me on Opera.
    Outstanding Blog!

  50. Amy Richards May 20, 2014 at 12:57 am #

    Good Work Christophe Coenraets, If you are serious about your writing, Write a Book: Get Published, Write Now! is as important a tool as your laptop or your pen. Do yourself a favor, and just buy it.

  51. Jithin George May 27, 2014 at 12:32 am #

    Hi,

    Thanks for this so informative article. I am new to the single page application developing area. I find the difficulty of more loading time in initial page loading. How can able to manage that ?

  52. seo advice May 29, 2014 at 6:38 am #

    I know this web page gives quality depending articles or reviws and additional information, is there
    any other website which offers such stuff in quality?

  53. ROR Development Company September 18, 2014 at 11:15 am #

    Great article post for us. I’ve learned a lot from your blog so far. Thanks

    please update some more new technology article like yii 2.0, cakephp latest version.

Trackbacks/Pingbacks

  1. Running Angularjs example with Slim for REST Service | question code - October 24, 2012

    […] Im having problem making this example for an angularjs application using slim(PHP framework for RESTful Webservice) to run properly. This is the link to the example http://coenraets.org/blog/2012/02/sample-application-with-angular-js/ […]

Leave a Reply

css.php