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.

  • 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.

  • 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.

  • 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

      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.

      • Cameron

        Amen!

  • 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!

  • Stanley

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

  • alex

    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

  • 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!

  • 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!!

  • 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).

  • nilay

    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…

  • Lee Chee Keong

    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

  • Narretz

    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

      @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?

  • Mark

    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

  • 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!!!

  • Pingback: Running Angularjs example with Slim for REST Service | question code()

  • Gilvam

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

    • Jim

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

    • Jim

      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.

  • Bob Dole

    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.)

  • 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.

  • 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!

  • 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!

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

  • Chris Lee

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

  • Chandra

    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.

  • Rob

    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

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

      • Jeff Jones

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

  • dilip

    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

  • Chris Lee

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

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

  • 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

  • Satwati

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

  • Robin

    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 ?

  • 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.

  • Alter that shoes into a full-scale Goldmine

  • ペリカン 万年筆 インク

  • jon smith

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

  • 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.

  • Ajeesh

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

  • sushant

    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

  • Jimmers

    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

    • eve

      I am getting the same error. Trying to figure out that /#/wines

      Anyone facing that same error?

  • Tim

    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…

  • This has an issue!

  • Karthik

    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.

  • 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

  • Pablo

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

  • 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

  • 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.

  • 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.

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

  • 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.

  • 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.

  • 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!

  • 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.

  • Jithin George

    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 ?

  • 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?

  • 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.

  • Ben Hannoun

    interesting tutorial !

    Many thank Christophe and Narretz

  • Pingback: [펌][AngularJS] 배우는 방법 & 기본 개념 잡기 | Window of Andrew, JEON()

  • Chandu

    Hello Sir,

    Thanks for excellent Tutorial. I downloaded the application and run in Tomcat server in eclipse IDE. It works Perfectly for delete, Retrieve list and Retrieve Details but not working for save and update. Please Guide me. Thanks in advance.

  • Pingback: 10 AngularJS CRUD App Demos | AngularJS 4U()

  • Thanks for tips. I am trying it.

  • Excellent tutorial!…I am looking for a tutorial on how you can capture wifi data…like the captive portal way and integrate it in an angular application. What I would wish for is to have users sign up using social media, and the data is stored into a remote existing angular app

  • Marcin

    Dear Sir

    What developer environment You’re using to create web application projects like this sample application (angular.js and Slim framework). Is this Aptana Studio 3 or Eclipse ? One developer software will integrate everything from project in one place.

    Thank You for any answer.

  • Hikaru AC

    i can’t see the connection to the database

  • Firmamızın en fazla üretim yaptığı, spor çoraplarında kullandığımız ürünler: pamuk ,koton, polyester, naylon ve likradır. Anti-bakteriyel içermektedir. Ayrıca her türlü özel logolu ve yazılı çorap üretimi yapılmaktadır. Futbol, basketbol, kısa çorap, soket çorabı, antreman çorapları üretilmektedir.

  • Examples are the best way to learn AngularJS. Assume you already know JAVASCRIPT, then what more you required? Only Examples are good enough to get basics of AngularJS. Look at this link http://jharaphula.com/category/programming-solutions/learn-angularjs-with-examples here I collected all the fundamentals of AngularJS. its easy n fun to learn.

  • Examples are the best way to learn AngularJS. Assume you already know JAVASCRIPT, then what more you required? Only Examples are good enough to get basics of AngularJS. Look at this link http://jharaphula.com/category/programming-solutions/learn-angularjs-with-examples here I collected all the fundamentals of AngularJS with examples. its easy n fun to learn.

  • Its really amazing blog post. useful for me a lot. Thank you.

  • Newton Moses

    Thanks a lot for providing us with a sample application with ngular.js. It is amazing how you are able to play around with these different programming languages. It’s now possible to get lit review experienced paraphrasers by simply clicking on this link: https://www.customwritingbay.ca/40-canadian-writers/1252-lit-review-paraphrasing-help

css.php