What is AngularJS?

AngularJS is a JavaScript MVC framework developed by Google that lets you build well structured, easily testable, and maintainable front-end applications.

And Why Should I Use It?

If you haven’t tried AngularJS yet, you’re missing out. The framework consists of a tightly integrated toolset that will help you build well structured, rich client-side applications in a modular fashion—with less code and more flexibility.

AngularJS extends HTML by providing directives that add functionality to your markup and allow you to create powerful dynamic templates. You can also create your own directives, crafting reusable components that fill your needs and abstracting away all the DOM manipulation logic.

It also implements two-way data binding, connecting your HTML (views) to your JavaScript objects (models) seamlessly. In simple terms, this means that any update on your model will be immediately reflected in your view without the need for any DOM manipulation or event handling (e.g., with jQuery).

Angular provides services on top of XHR that dramatically simplify your code and allow you to abstract API calls into reusable services. With that, you can move your model and business logic to the front-end and build back-end agnostic web apps.

Finally, I love Angular because of its flexibility regarding server communication. Like most JavaScript MVC frameworks, it lets you work with any server-side technology as long as it can serve your app through a RESTful web API. But Angular also provides services on top of XHR that dramatically simplify your code and allow you to abstract API calls into reusable services. As a result, you can move your model and business logic to the front-end and build back-end agnostic web apps. In this post, we’ll do just that, one step at a time.

So, Where Do I Begin?

First, let’s decide the nature of the app we want to build. In this guide, we’d prefer not to spend too much time on the back-end, so we’ll write something based on data that’s easily attainable on the Internet—like a sports feed app!

Since I happen to be a huge fan of motor racing and Formula 1, I’ll use an autosport API service to act as our back-end. Luckily, the guys at Ergast are kind enough to provide a free motorsport API that will be perfect for us.

For a sneak peak at what we’re going to build, take a look at the live demo. To prettify the demo and show off some Angular templating, I applied the awesome Plastic Admin Bootstrap theme; but seeing as this article isn’t about CSS, I’ll just abstract it away from the examples and leave it out.

Getting Started

Let’s kickstart our example app with some boilerplate. I recommend the angular-seed project as it not only provides you with a great skeleton for bootstrapping, but also sets the ground for unit testing with Karma and Jasmine (we won’t be doing any testing in this demo, so we’ll just leave that stuff aside for now; see Part 2 of this tutorial for more info on setting up your project for unit and end-to-end testing).

EDIT (May 2014): Since I wrote this tutorial, the angular-seed project has gone through some heavy changes (including the additon of Bower as package manager). If you have any doubts about how to deploy the project, take a quick look at the first section of their reference guide. In Part 2 of ths tutorial, Bower, among other tools, is covered in greater detail.

OK, now that w’ve cloned the repository and installed the dependencies, our app’s skeleton will look like this:

Now we can start coding. As we’re trying to build a sports feed for a racing championship, let’s begin with the most relevant view: the championship table.

Given that we already have a drivers list defined within our scope (hang with me – we’ll get there), and ignoring any CSS (for readability), our HTML might look like:

<body ng-app="F1FeederApp" ng-controller="driversController">
  <table>
    <thead>
      <tr><th colspan="4">Drivers Championship Standings</th></tr>
    </thead>
    <tbody>
      <tr ng-repeat="driver in driversList">
        <td>{{$index + 1}}</td>
        <td>
          <img src="img/flags/{{driver.Driver.nationality}}.png" />
          {{driver.Driver.givenName}}&nbsp;{{driver.Driver.familyName}}
        </td>
        <td>{{driver.Constructors[0].name}}</td>
        <td>{{driver.points}}</td>
      </tr>
    </tbody>
  </table>
</body>

The first thing you’ll notice in this template is the use of expressions (“{{“ and “}}”) to return variable values. In AngularJS, expressions allow you to execute some computation in order to return a desired value. Some valid expressions would be:

  • {{ 1 + 1 }}
  • {{ 946757880 | date }}
  • {{ user.name }}

Effectively, expressions are JavaScript-like snippets. But despite being very powerful, you shouldn’t use expressions to implement any higher-level logic. For that, we use directives.

Understanding Basic Directives

The second thing you’ll notice is the presence of ng-attributes, which you wouldn’t see in typical markup. Those are directives.

At a high level, directives are markers (such as attributes, tags, and class names) that tell AngularJS to attach a given behaviour to a DOM element (or transform it, replace it, etc.). Let’s take a look at the ones we’ve seen already:

  • The ng-app directive is responsible for bootstrapping your app defining its scope. In AngularJS, you can have multiple apps within the same page, so this directive defines where each distinct app starts and ends.

  • The ng-controller directive defines which controller will be in charge of your view. In this case, we denote the driversController, which will provide our list of drivers (driversList).

  • The ng-repeat directive is one of the most commonly used and serves to define your template scope when looping through collections. In the example above, it replicates a line in the table for each driver in driversList.

Adding Controllers

Of course, there’s no use for our view without a controller. Let’s add driversController to our controllers.js:

angular.module('F1FeederApp.controllers', []).
controller('driversController', function($scope) {
    $scope.driversList = [
      {
          Driver: {
              givenName: 'Sebastian',
              familyName: 'Vettel'
          },
          points: 322,
          nationality: "German",
          Constructors: [
              {name: "Red Bull"}
          ]
      },
      {
          Driver: {
          givenName: 'Fernando',
              familyName: 'Alonso'
          },
          points: 207,
          nationality: "Spanish",
          Constructors: [
              {name: "Ferrari"}
          ]
      }
    ];
});

You may have noticed the $scope variable we’re passing as a parameter to the controller. The $scope variable is supposed to link your controller and views. In particular, it holds all the data that will be used within your template. Anything you add to it (like the driversList in the above example) will be directly accessible in your views. For now, let’s just work with a dummy (static) data array, which we will replace later with our API service.

Now, add this to app.js:

angular.module('F1FeederApp', [
  'F1FeederApp.controllers'
]);

With this line of code, we actually initialize our app and register the modules on which it depends. We’ll come back to that file (app.js) later on.

Now, let’s put everything together in index.html:

<!DOCTYPE html>
<html>
<head>
  <title>F-1 Feeder</title>
</head>

<body ng-app="F1FeederApp" ng-controller="driversController">
  <table>
    <thead>
      <tr><th colspan="4">Drivers Championship Standings</th></tr>
    </thead>
    <tbody>
      <tr ng-repeat="driver in driversList">
        <td>{{$index + 1}}</td>
        <td>
          <img src="img/flags/{{driver.Driver.nationality}}.png" />
          {{driver.Driver.givenName}}&nbsp;{{driver.Driver.familyName}}
        </td>
        <td>{{driver.Constructors[0].name}}</td>
        <td>{{driver.points}}</td>
      </tr>
    </tbody>
  </table>
  <script src="bower_components/angular/angular.js"></script>
  <script src="bower_components/angular-route/angular-route.js"></script>
  <script src="js/app.js"></script>
  <script src="js/services.js"></script>
  <script src="js/controllers.js"></script>
</body>
</html>

Modulo minor mistakes, you can now boot up your app and check your (static) list of drivers.

Note: If you need help debugging your app and visualizing your models and scope within the browser, I recommend taking a look at the awesome Batarang plugin for Chrome.

Loading Data From the Server

Since we already know how to display our controller’s data in our view, it’s time to actually fetch live data from a RESTful server.

To facilitate communication with HTTP servers, AngularJS provides the $http and $resource services. The former is but a layer on top of XMLHttpRequest or JSONP, while the latter provides a higher level of abstraction. We’ll use $http.

To abstract our server API calls from the controller, let’s create our own custom service which will fetch our data and act as a wrapper around $http by adding this to our services.js:

angular.module('F1FeederApp.services', []).
  factory('ergastAPIservice', function($http) {

    var ergastAPI = {};

    ergastAPI.getDrivers = function() {
      return $http({
        method: 'JSONP', 
        url: 'http://ergast.com/api/f1/2013/driverStandings.json?callback=JSON_CALLBACK'
      });
    }

    return ergastAPI;
  });

With the first two lines, we create a new module (F1FeederApp.services) and register a service within that module (ergastAPIservice). Notice that we pass $http as a parameter to that service. This tells Angular’s dependency injection engine that our new service requires (or depends on) the $http service.

In a similar fashion, we need to tell Angular to include our new module into our app. Let’s register it with app.js, replacing our existing code with:

angular.module('F1FeederApp', [
  'F1FeederApp.controllers',
  'F1FeederApp.services'
]);

Now, all we need to do is tweak our controller.js a bit, include ergastAPIservice as a dependency, and we’ll be good to go:

angular.module('F1FeederApp.controllers', []).
  controller('driversController', function($scope, ergastAPIservice) {
    $scope.nameFilter = null;
    $scope.driversList = [];

    ergastAPIservice.getDrivers().success(function (response) {
        //Dig into the responde to get the relevant data
        $scope.driversList = response.MRData.StandingsTable.StandingsLists[0].DriverStandings;
    });
  });

Now reload the app and check out the result. Notice that we didn’t make any changes to our template, but we added a nameFilter variable to our scope. Let’s put that variable to use.

Filters

Great! We have a functional controller. But it only shows a list of drivers. Let’s add some functionality by implementing a simple text search input which will filter our list. Let’s add the following line to our index.html, right below the <body> tag:

<input type="text" ng-model="nameFilter" placeholder="Search..."/>

We are now making use of the ng-model directive. This directive binds our text field to the $scope.nameFilter variable and makes sure that its value is always up-to-date with the input value. Now, let’s visit index.html one more time and make a small adjustment to the line that contains the ng-repeat directive:

<tr ng-repeat="driver in driversList | filter: nameFilter">

This line tells ng-repeat that, before outputting the data, the driversList array must be filtered by the value stored in nameFilter.

At this point, two-way data binding kicks in: every time a value is input in the search field, Angular immediately ensures that the $scope.nameFilter that we associated with it is updated with the new value. Since the binding works both ways, the moment the nameFilter value is updated, the second directive associated to it (i.e., the ng-repeat) also gets the new value and the view is updated immediately.

Reload the app and check out the search bar.

Notice that this filter will look for the keyword on all attributes of the model, including the ones we´re not using. Let’s say we only want to filter by Driver.givenName and Driver.familyName: First, we add to driversController, right below the $scope.driversList = []; line:

$scope.searchFilter = function (driver) {
    var keyword = new RegExp($scope.nameFilter, 'i');
    return !$scope.nameFilter || keyword.test(driver.Driver.givenName) || keyword.test(driver.Driver.familyName);
};

Now, back to index.html, we update the line that contains the ng-repeat directive:

<tr ng-repeat="driver in driversList | filter: searchFilter">

Reload the app one more time and now we have a search by name.

Routes

Our next goal is to create a driver details page which will let us click on each driver and see his/her career details.

First, let’s include the $routeProvider service (in app.js) which will help us deal with these varied application routes. Then, we’ll add two such routes: one for the championship table and another for the driver details. Here’s our new app.js:

angular.module('F1FeederApp', [
  'F1FeederApp.services',
  'F1FeederApp.controllers',
  'ngRoute'
]).
config(['$routeProvider', function($routeProvider) {
  $routeProvider.
	when("/drivers", {templateUrl: "partials/drivers.html", controller: "driversController"}).
	when("/drivers/:id", {templateUrl: "partials/driver.html", controller: "driverController"}).
	otherwise({redirectTo: '/drivers'});
}]);

With that change, navigating to “http://domain/#/drivers” will load the driversController and look for the partial view to render in partials/drivers.html. But wait! We don’t have any partial views yet, right? We’ll need to create those too.

Partial Views

AngularJS will allow you to bind your routes to specific controllers and views.

But first, we need to tell Angular where to render these partial views. For that, we’ll use the ng-view directive, modifying our index.html to mirror the following:

<!DOCTYPE html>
<html>
<head>
  <title>F-1 Feeder</title>
</head>

<body ng-app="F1FeederApp">
  <ng-view></ng-view>
  <script src="bower_components/angular/angular.js"></script>
  <script src="bower_components/angular-route/angular-route.js"></script>
  <script src="js/app.js"></script>
  <script src="js/services.js"></script>
  <script src="js/controllers.js"></script>
</body>
</html>

Now, whenever we navigate through our app routes, Angular will load the associated view and render it in place of the <ng-view> tag. All we need to do is create a file named partials/drivers.html and put our championship table HTML there. We’ll also use this chance to link the driver name to our driver details route:

<input type="text" ng-model="nameFilter" placeholder="Search..."/>
<table>
<thead>
  <tr><th colspan="4">Drivers Championship Standings</th></tr>
</thead>
<tbody>
  <tr ng-repeat="driver in driversList | filter: searchFilter">
    <td>{{$index + 1}}</td>
    <td>
      <img src="img/flags/{{driver.Driver.nationality}}.png" />
      <a href="#/drivers/{{driver.Driver.driverId}}">
	  	{{driver.Driver.givenName}}&nbsp;{{driver.Driver.familyName}}
	  </a>
	</td>
    <td>{{driver.Constructors[0].name}}</td>
    <td>{{driver.points}}</td>
  </tr>
</tbody>
</table>

Finally, let’s decide what we want to show in the details page. How about a summary of all the relevant facts about the driver (e.g., birth, nationality) along with a table containing his/her recent results? To do that, we add to services.js:

angular.module('F1FeederApp.services', [])
  .factory('ergastAPIservice', function($http) {

    var ergastAPI = {};

    ergastAPI.getDrivers = function() {
      return $http({
        method: 'JSONP', 
        url: 'http://ergast.com/api/f1/2013/driverStandings.json?callback=JSON_CALLBACK'
      });
    }

    ergastAPI.getDriverDetails = function(id) {
      return $http({
        method: 'JSONP', 
        url: 'http://ergast.com/api/f1/2013/drivers/'+ id +'/driverStandings.json?callback=JSON_CALLBACK'
      });
    }

    ergastAPI.getDriverRaces = function(id) {
      return $http({
        method: 'JSONP', 
        url: 'http://ergast.com/api/f1/2013/drivers/'+ id +'/results.json?callback=JSON_CALLBACK'
      });
    }

    return ergastAPI;
  });

This time, we provide the driver’s ID to the service so that we retrieve the information relevant solely to a specific driver. Now, we modify controllers.js:

angular.module('F1FeederApp.controllers', []).

  /* Drivers controller */
  controller('driversController', function($scope, ergastAPIservice) {
    $scope.nameFilter = null;
    $scope.driversList = [];
    $scope.searchFilter = function (driver) {
        var re = new RegExp($scope.nameFilter, 'i');
        return !$scope.nameFilter || re.test(driver.Driver.givenName) || re.test(driver.Driver.familyName);
    };

    ergastAPIservice.getDrivers().success(function (response) {
        //Digging into the response to get the relevant data
        $scope.driversList = response.MRData.StandingsTable.StandingsLists[0].DriverStandings;
    });
  }).

  /* Driver controller */
  controller('driverController', function($scope, $routeParams, ergastAPIservice) {
    $scope.id = $routeParams.id;
    $scope.races = [];
    $scope.driver = null;

    ergastAPIservice.getDriverDetails($scope.id).success(function (response) {
        $scope.driver = response.MRData.StandingsTable.StandingsLists[0].DriverStandings[0]; 
    });

    ergastAPIservice.getDriverRaces($scope.id).success(function (response) {
        $scope.races = response.MRData.RaceTable.Races; 
    }); 
  });

The important thing to notice here is that we just injected the $routeParams service into the driver controller. This service will allow us to access our URL parameters (for the :id, in this case) using $routeParams.id.

Now that we have our data in the scope, we only need the remaining partial view. Let’s create a file named partials/driver.html and add:

<section id="main">
  <a href="./#/drivers"><- Back to drivers list</a>
  <nav id="secondary" class="main-nav">
    <div class="driver-picture">
      <div class="avatar">
        <img ng-show="driver" src="img/drivers/{{driver.Driver.driverId}}.png" />
        <img ng-show="driver" src="img/flags/{{driver.Driver.nationality}}.png" /><br/>
        {{driver.Driver.givenName}} {{driver.Driver.familyName}}
      </div>
    </div>
    <div class="driver-status">
      Country: {{driver.Driver.nationality}}   <br/>
      Team: {{driver.Constructors[0].name}}<br/>
      Birth: {{driver.Driver.dateOfBirth}}<br/>
      <a href="{{driver.Driver.url}}" target="_blank">Biography</a>
    </div>
  </nav>

  <div class="main-content">
    <table class="result-table">
      <thead>
        <tr><th colspan="5">Formula 1 2013 Results</th></tr>
      </thead>
      <tbody>
        <tr>
          <td>Round</td> <td>Grand Prix</td> <td>Team</td> <td>Grid</td> <td>Race</td>
        </tr>
        <tr ng-repeat="race in races">
          <td>{{race.round}}</td>
          <td><img  src="img/flags/{{race.Circuit.Location.country}}.png" />{{race.raceName}}</td>
          <td>{{race.Results[0].Constructor.name}}</td>
          <td>{{race.Results[0].grid}}</td>
          <td>{{race.Results[0].position}}</td>
        </tr>
      </tbody>
    </table>
  </div>

</section>

Notice that we’re now putting the ng-show directive to good use. This directive will only show the HTML element if the expression provided is true (i.e., neither false, nor null). In this case, the avatar will only show up once the driver object has been loaded into the scope by the controller.

Finishing Touches

Add in a bunch of CSS and render your page. You should end up with something like this:

You’re now ready to fire up your app and make sure both routes are working as desired. You could also add a static menu to index.html to improve the user’s navigation capabilities. The possibilities are endless.

EDIT (May 2014): I’ve received many requests for a downloadable version of the code that we build in this tutorial. I’ve therefore decided to release it here (stripped of any CSS). However, I really do not recommend downloading it, since this guide contains every single step you need to build the same application with your own hands, which will be a much more useful and effective learning exercise.

Conclusion

At this point in the tutorial, we’ve covered everything you’d need to write a simple app (like a Formula 1 feeder). Each of the remaining pages in the live demo (e.g., constructor championship table, team details, calendar) share the same basic structure and concepts that we’ve reviewed here.

Finally, keep in mind that Angular is a very powerful framework and we’ve barely scratched the surface in terms of everything it has to offer. In Part 2 of this tutorial, we’ll give examples of why Angular stands out among its peer front-end MVC frameworks: testability. We’ll review the process of writing and running unit tests with Karma, achieving continuous integration with Yeomen, Grunt, and Bower, and other strengths of this fantastic front-end framework.

Looking to hire top engineers? Check out Toptal's AngularJS developers!
Editor's note: want posts just like this delivered straight to your inbox? Subscribe below to receive our latest engineering articles.
Subscribe to our engineering blog for the latest tips

Comments

Alexandre Wiechers Vaz
Excellent article! As a suggestion, I think that would be really great if you write an article about using Angular along with a Node.js backend!
Antonio Cachuan
Thanks, I was looking for this tutorial.
Julien L
Thanks for the article. Easier to follow than the official ones.
Alan
Nice article with very good api example. Only 2 problems. 1. Images didn't load. 2. If I enter 'pa' in search box, I get Paul di Rosta and Pastor Maldanado ok but I also get Fernando Alonso?
David Bocle
1. Images won't load because we do not have any CSS. 2. Alonso shows up because it filtered it's nationality too which is "sPAnish", a little tweak on the filter would arrange that :)
Alan
Thanks for your quick reply. Have added another filter to block Nationality and works well. Looking forward to next article.
Raoni Boaventura
Hey Alan! 1. The images will not load for you simply because they are not there to be loaded (sorry, but I'm not allowed to share the whole CSS with you guys since i'm using someone else's theme), the point of there was just to show how to make an image request. 2. As David pointed out, since i didn't specify which attributes are supposed to be filtered, Angular will consider all attributes of the model (even the ones that are not being printed) and Alonso will show up positive for "pa" because he is s"pa"nish. Thank you for you feedback on that, I shall add a note about it on the text.
Vivek Mishra
Very nice article!! Got it working on my LAMP setup :-). It's really powerful and easy to use framework.
Thomas Murphy
Hi Raoni, Lovely article. I would suggestion adding error handling to the $http portions. I know this article doesn't cover testing, but I feel this is baseline for making one's app durable.
jimbavia
Big THANKS to you. Great Article
santiago
If use Node with sockets, angular sucks
Cesar William
Great article!! Just one correction: where you use filterName just change to nameFilter.
weakish
Nice article. I have translated it into Chinese: http://segmentfault.com/a/1190000000347412
Raoni Boaventura
That's great, man! Nice work!
Raoni Boaventura
I updated the text and removed the mistake. Thanks for noticing!
Matías Fernández
Great article!! is there any chance you could upload the full source code? thanks a lot!
daneroo
Great article, can't wait for the followup with karma and yeoman.
sathiya R
Raoni, Thanks for the nice ariticle. If i am using MVC4 along with AngularJs, do i need to maintain MVC structure on both Server-side and client-side? please help me to define project structure
rsschouwenaar
Nice tutorial :D
devour
How were you able to retrieve the JSONP from Ergast? When fetching the Driver data locally I can get the to app work, but when I try fetching the data from Ergast I don't see any driver data in my index.html. When I chain .error(err, status) to ergastAPIservice.getDrivers(), it gets called and I can see that the status = 0 in the console (and err = undefined). I'm using the angular-seed project and running it's web-server.js with node.js. Any idea on what the problem could be?
Shakeel
WOW. I learned Angular today.
Megrem Lingroar
in the image tags, use ng-src instead of src ...
Jatin Mankodiya
Really a great article
benlagrone
Thanks, this really helped me put it all together
Vishal Kotcherlakota
Fantastic. I've been hopelessly hacking away at Angular before now. This is exactly what I was looking for!
Vikrant
Did you try using ng-grid for displaying the data. I tried ng-grid, and was able to display the data when the data resided inside the controller. But ng-grid did not work when reading the data from web-service. Anyone tried using ng-grid?
Chandu
HI Devour, I also faced the same issue. Did you get a solution for it.
JeongHwan Mun
Nice Article!
devour
No unfortunately I wasn't able to figure it out :( I thought it may have been due to CORS, so I tried setting different headers with node.js but still couldn't get it to work. If I ever return to this problem and find a solution, I'll post it here.
anand kumar
Good article!! Please share the source code
Sagar Das
Excellent !!! So very clear and easy to understand.
Anna
Thanks for the tutorial, it was good. Could please make a follow up of this tutorial: e.g. testing this formula 1 app with jasmine and karma. I also have another question, in chrome I constantly getting this error in the console: when I start the app: [code] GET http://localhost:8080/formula1/img/flags/%7B%7Bdriver.Driver.nationality%7D%7D.png 404 (Not Found) angular.min.js:144 GET http://localhost:8080/formula1/img/flags/%7B%7Bdriver.Driver.nationality%7D%7D.png 404 (Not Found) angular.min.js:26[/code] when I select a racer:[code] GET http://localhost:8080/formula1/img/flags/%7B%7Brace.Circuit.Location.country%7D%7D.png 404 (Not Found) angular.min.js:144 GET http://localhost:8080/formula1/img/flags/.png 404 (Not Found) angular.min.js:143 GET http://localhost:8080/formula1/img/flags/%7B%7Brace.Circuit.Location.country%7D%7D.png 404 (Not Found) angular.min.js:26 [/code] Why is this happening? Btw I see all the flags and remove the drivers img tag
aly noor
It should be driver.nationality and not driver.Driver.nationality when we do a static load from JSONs.
Sarad Mohanan
great article!
SHIVAPRASAD
if we want to search using a same grid number can we get all the rows regarding those grid number please help
lay dies& gentle men
Hey, thanks for this helpful example! I did notice a small error though. In the early controller example (when the json is coming directly from the controller) the correct json example should be: controller('driversController', function($scope) { $scope.driversList = [ { Driver: { nationality: "German", givenName: 'Sebastian', familyName: 'Vettel' }, points: 322, Constructors: [ {name: "Red Bull"} ] }, { Driver: { nationality: "Spanish", givenName: 'Fernando', familyName: 'Alonso' }, points: 207, Constructors: [ {name: "Ferrari"} ] }]; }); This is bacuase you were calling nationality like this in the img src: src="img/flags/{{driver.Driver.nationality}}.png" Also, should be ng-src not src :D Thanks a lot for your example!
Sweeta Rebero
Hi, I really did like this tutorial, thanks. Although, I did notice the following : When explaining about "ROUTES" one of the dependencies i.e 'ngRoute', did not work for me. When I changed it to 'ui.router', it started working though. Did i miss anything for it to not work with 'ngRoute'?
Raoni Boaventura
Hey Sweeta! You did absolutely nothing wrong... The problem is that the guys that develop the angular-seed project changed the way things work on their boilerplate and now I realized my tutorial is no longer up to date :( I'll make the necessary adjustments so other people don't have the same problem. Thanks for letting me know that. I wouldn't have noticed if it was not for you.
Majid Lotfi
Hi, Thanks for this tutorial, I am asking the same question other people asked before me : Where is the source code ?? but it looks like you don't want to answer it at all. thanks
sinnix
I came for the tutorial, I stayed for the F1 references. Nice job, thank you very much! :)
ALAN ANDRES CABRERA ABANTO
for load the flag and driver pictures change paths like img/flags/... for this http://rboaventura.com/f1feeder/images/ (sorry my bad english :D)
Majid Lotfi
HI, Thank you for posting the source code, I appreciate your help. I downloaded the source code BUT when I want to start the server I got this : C:\Users\alotfi\UIs\angularjsProjs\f1feeder-part1-master>npm start > angular-seed@0.0.0 prestart C:\Users\alotfi\UIs\angularjsProjs\f1feeder-part1-master > npm install > angular-seed@0.0.0 postinstall C:\Users\alotfi\UIs\angularjsProjs\f1feeder-part1-master > bower install bower angular#1.2.x ENOGIT git is not installed or not in the PATH npm ERR! angular-seed@0.0.0 postinstall: `bower install` npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the angular-seed@0.0.0 postinstall script. npm ERR! This is most likely a problem with the angular-seed package, npm ERR! not with npm itself. npm ERR! Tell the author that this fails on your system: npm ERR! bower install npm ERR! You can get their info via: npm ERR! npm owner ls angular-seed npm ERR! There is likely additional logging output above. npm ERR! System Windows_NT 6.1.7601 npm ERR! command "C:\\Program Files\\nodejs\\\\node.exe" "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "install" npm ERR! cwd C:\Users\alotfi\UIs\angularjsProjs\f1feeder-part1-master npm ERR! node -v v0.10.28 npm ERR! npm -v 1.4.9 npm ERR! code ELIFECYCLE npm ERR! npm ERR! Additional logging details can be found in: npm ERR! C:\Users\alotfi\UIs\angularjsProjs\f1feeder-part1-master\npm-debug.log npm ERR! not ok code 0 npm ERR! angular-seed@0.0.0 prestart: `npm install` npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the angular-seed@0.0.0 prestart script. npm ERR! This is most likely a problem with the angular-seed package, npm ERR! not with npm itself. npm ERR! Tell the author that this fails on your system: npm ERR! npm install npm ERR! You can get their info via: npm ERR! npm owner ls angular-seed npm ERR! There is likely additional logging output above. npm ERR! System Windows_NT 6.1.7601 npm ERR! command "C:\\Program Files\\nodejs\\\\node.exe" "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "start" npm ERR! cwd C:\Users\alotfi\UIs\angularjsProjs\f1feeder-part1-master npm ERR! node -v v0.10.28 npm ERR! npm -v 1.4.9 npm ERR! code ELIFECYCLE npm ERR! npm ERR! Additional logging details can be found in: npm ERR! C:\Users\alotfi\UIs\angularjsProjs\f1feeder-part1-master\npm-debug.log npm ERR! not ok code 0 Your help is appreciated.
Raoni Boaventura
Hey man... Apparently, you don't have bower installed. Check part two of this tutorial for details on how to install it and in the meantime i'll add a note on github so other people don't have the same problem.. Thanks for the feedback!
Raoni Boaventura
Creative thinking there :) Just to let you know, I also just made the source code available on github and the images are all there.
Majid Lotfi
it's working now, I had to do : npm install. I got little bit confused : when we have to do : bower install and when we have to do : npm install ? Thanks
Raoni Boaventura
You don't have to explicitly do "bower install" in this case (npm install does both for you).
Adrian Frimmy
What's your code look like for your ergast service?
Adrian Frimmy
Goes w/o saying, solid tut/article, looking forward to pt2!
Adrian Frimmy
broken link?
ALAN ANDRES CABRERA ABANTO
I think that link is good for example look this flag http://rboaventura.com/f1feeder/images/flags/German.png
Venkat
that's really great. please share source code
Venkat
please share the source code. thanks in advance
Vivek Mishra
Download & Extract the zip file in htdocs folder: https://app.box.com/s/oc4dzvumdhw4mc6krel5 I am gonna remove this link very soon. As doing on your own is the best way to learn & I guess that's why author has not provided the "download code link" :)
Senthil Rajendran
Got a big picture on angular , special thanks
Mr. Blunt
I really liked this article and explained most of basic stuff with Angular. I have one question though, when I hit the default route, I see that there are 2 GET calls to the same API. I am wondering how we could control this.
Carlos Barros
I really hate tutorials like these, I expect to create all from scratch including the routes, not svn checkout, run ant scripts or some magic that hides all important and essencial keys to build. Its a tutorial doesnt have to be fast but we have to UNDERSTAND what is going on.
lujaw
very good article, thanks for sharing..
CameronJRoe
Good read. ngRoute is a bit outdated. Using ui.router makes a little more sense considering you can do the same as ngRoute and more with the stateProvider. Cheers!
girish sakhare
We can also further add a ddl for year and invoke the service on change of year using $watch
Cody
Nice work! I appreciated your clear writing style and concrete examples. Racing makes for an interesting theme, too.
Hafiz Faraz Mukhtar
http://blog.hfarazm.com/getting-started-angular-js/
Imdadhusen Sunasara
Really awesome work. Great representation and point to point explanation. Minor correction for static data display. In exsting code you have used driver.Driver.nationality <img src="img/flags/{{driver.Driver.nationality}}.png" /> but it should be only driver.nationality <img src="img/flags/{{driver.nationality}}.png" /> Your article is really helped me a lot, Thanks again for nice and hard work. Imdadhusen
Ram
great!!!!! Thanks a lot...............
Mohana babu
Its good acritical to learn angular . Could you please share the source code.
Raoni Boaventura
It's already available here https://github.com/raonibr/f1feeder-part1 The link was in the post... But maybe I should put it somewhere more obvious.
Michael Horozinskij
Hello dudes ... i have question what develop area i use to develop AngularJS? thanks.
Jamie Bisimo
framework sucks if the developer sucks.
Guest
plujoi
JenAdkins
I also have this error angular-seed@0.0.0 postinstall: `bower install' and I have git installed, so that doesnt appear to be the issue. Any other suggestions?
Raoni Boaventura
This is not the error... That's the expected output. If you indeed have an error, then I think you pasted the wrong portion of the log. It's hard to tell whats happenning without the actual error.
Nadeem
Thanks for the code
Mohamed Jubair
Thanks for this useful article! <a href="http://www.changepond.com/site/angularjs-overview">AngularJS Developers</a>
thomasvs
Following the tutorial. In the table, you use driver.Driver.nationality, but in the sample driversList nationality is next to instead of under Driver. So nationality doesn't expand properly. Fix either the call to use it or the location of nationality in driversList.
Joanna Lin
Ermagherd, this is too good!! Thanks a lot!!!
Suraj
Awesome Article!, can you help me with running this app with node server.
Andy Wong
Hi, Many thanks for the tutorial. I followed all steps as required till I ran this line 'npm start' Then I got the following errors... andy@LINUXAWCM:~/Projects/Javascript/f1feeder-app$ npm start > angular-seed@0.0.0 prestart /home/andy/Projects/Javascript/f1feeder-app > npm install npm ERR! angular-seed@0.0.0 prestart: `npm install` npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the angular-seed@0.0.0 prestart script. npm ERR! This is most likely a problem with the angular-seed package, npm ERR! not with npm itself. npm ERR! Tell the author that this fails on your system: npm ERR! npm install npm ERR! You can get their info via: npm ERR! npm owner ls angular-seed npm ERR! There is likely additional logging output above. npm ERR! System Linux 3.11.0-26-generic npm ERR! command "node" "/usr/local/bin/npm" "start" npm ERR! cwd /home/andy/Projects/Javascript/f1feeder-app npm ERR! node -v v0.6.12 npm ERR! npm -v 1.3.26 npm ERR! code ELIFECYCLE npm ERR! npm ERR! Additional logging details can be found in: npm ERR! /home/andy/Projects/Javascript/f1feeder-app/npm-debug.log npm ERR! not ok code undefined npm ERR! not ok code 1 I could not go further as there's no clues in the log that would suggest to tell me how to resolve it... Any ideas what I need to do next?
Antony Raj
hey... It is minor correction. it does't work with static data. but works well with service data. problem with structure of JSON data. it is very nice article.
Sameera Thilakasiri
Thankx for best ways to teach angular js
comments powered by Disqus
Subscribe
Subscribe to Engineering Articles by Email
Trending articles
Relevant technologies