AngularJS Workshop

This started out as a lesson plan for my 3rd Year Undergraduate students, so I've cut out a bit of the 'introductory' stuff on the assumption that if you're here you've read up a bit on Angular.

Hopefully as this is what I'm delivering to my students it should be easy to follow!

NOTE: I'm a bit of an Angular newbie myself, and this is just a write up of my own little Hello World experiment, so please let me know if I've fundamentally misunderstood anything here in the comments!

Set Up Files

For this workshop we will need an index.html for all our HTML and app.js for all our JavaScript. Call the app.js at the bottom of your index file. You may also want to use some CSS.

Prior to calling app.js, you will also need to include Angular. You can grab that from cdnjs.com

  <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.20/angular.min.js"></script>

Of course, if you're using Codepen you just need to select the Angular library in the JS settings.

Create a 'self invoking' function

First we need to create a function to hold all of our app code.

  (function(){
// some code…
})();

The last () is so the functionality is called right away. It is called a 'self invoking function' - A bit like document.ready.

Declaring an App

  var app = angular.module('testApp',[]);

First off we give our app a name - in this case 'testApp'. The empty array ([]) is where we can put any dependencies that our app requires - in this example we don't need any (however, you still need to include the empty array).

  <body ng-app="testApp">

We now need to connect our app to our HTML. Usually this would be done on the <body> tag, but it works just as well on any HTML element, as long as the rest of our app HTML is contained within.

Create controller

Add the following code after you declare the app, but inside the main function.

  app.controller('testController', function($scope){

});

A controller is where we can store some functionality, logic and data. Again we need to name it, and there is also the ability to add any dependencies should we need to (although I haven't included this in the example).

$scope is a special Angular variable that binds data to the controller. Anything that calls on $scope is limited and bound to the controller it is in.

  <div ng-controller="testController as test"></div>

Again, we need to connect our controller with our HTML. Everything inside this <div> will be able to access functionality and data from the controller.

Here we are 'aliasing' our controller, so that we can call it in our view as 'test' rather than 'testController'. In actuality, the use of $scope means that in this example I don't need to call on the controller in the view - however, it is still worth getting in to the habit of aliasing controllers in the HTML.

Create and display data

  $scope.title = "Hello, World!";

Add this code inside your controller to create a new property 'title' of our $scope variable equal to 'Hello, World'.

  {{title}}

This is how Angular template tags appear, with double handlebar brackets and the data property between them. Place this anywhere inside the controller in your HTML that you want the data to show

To understand $scope, try moving {{title}} outside of the controller <div>. What happens?

Angular HTML attributes

Angular has lots of built in functionality that we can call directly in the HTML by using special Angular attributes in our tags. These all start ng- and there are several examples below.

ng-model

One of the key features of Angular is two way data binding. This means that we can change the data directly in the view without running a function.

  <input type="text" ng-model="title"/>

Add this text input with an ng-model="title" attribute. Update the text field and see the title update on the page.

JavaScript Objects and JSON

In JavaScript, aside from variables and arrays, more complicated datasets are written in as objects {} with key and value pairs, and we can store several objects inside an array []. It's a very simple way to write data, and an example data set is below. Add it to your app.js within the controller.

  $scope.products = [
  {
  name: 'Product One',
  price: 2,
  forSale: true
  },
  {
  name: 'Product Two',
  price: 5,
  forSale: false
  },
  {
  name: 'Product Three',
  price: 9,
  forSale: true
  }
];

Here we have 3 different data types - a string (text, written inside ''), a number, and a boolean (true/false). We are adding this data as a property 'products' of our $scope variable.

Note: 'Products' is just an example. The data can be anything as a property of the $scope variable.

JSON stands for JavaScript Object Notation, and is a data format that has a similar syntax to how we write objects in JavaScript. For our data, we are putting objects in to an array, however we could write a separate JSON file and pull data in from there. (Thanks to Josh Eaton in the comments for pulling me up on my original explanation of this!)

The great thing about using JSON to drive the data in our app is you could pull data in from a separate .json file, or use a fully featured database like MongoDB.

ng-repeat

Now we have a data set we can loop through it to extract the data.

Whereas in something like JQuery if we wanted to loop through a set of data and output it in to HTML we'd have to do it all in the script, spitting out big chunks of html. However, with Angular we can use ng-repeat to loop through the data right in the HTML.

  <li ng-repeat="product in products">
    {{product.name}} - {{product.price}}
</li>

Here we specify a single name for each entry in our data set. In this case 'product' inside the set 'products'. I could call the single name anything, however the data set name must match the property we set in the app.js.

I can then call individual properties of each entry and output them inside the template tags.

This example will out put an <li> with the name and price for every entry.

ng-filter

Angular has a set of built in filters we can apply to data. If we add a filter to our product price template tag, we can set the price to show as currency.

You add filters using a pipe symbol |

  {{product.price | currency}}

The default will show as '$', however if I want to show another currency I can by passing an argument in to the filter:

  {{product.price | currency: "£"}}

My ng-repeat template so far now looks like this:

  <li ng-repeat="product in products">
    {{product.name}} - {{product.price | currency: "£"}}
</li>

ng-show/ng-hide

A really useful Angular feature is being able to show and hide content based on data. Here, I'm only showing products that have a forSale value equal to 'true'.

You can also use logic here, for example checking if data is >= a value.

  ng-show="{{product.forSale}}"

My ng-repeat template so far now looks like this:

  <li ng-repeat="product in products" ng-show="{{product.forSale}}">
    {{product.name}} - {{product.price | currency: "£"}}
</li>

ng-class

Similar to ng-show and ng-hide, ng-class allows me to add a class to an element based on a data value. Here, I want to add a class of 'bargain' if a product price is less than £4.

  ng-class="{bargain: product.price <= 4}"

First I specify a class, and then I pass the argument to it after a colon.

My final ng-repeat template now looks like this:

  <li ng-repeat="product in products" ng-show="{{product.forSale}}" ng-class="{bargain: product.price <= 4}">
    {{product.name}} - {{product.price | currency: "£"}}
</li>

Create Add Product Form

Finally, I want to create some functionality that allows me to add a new product to my dataset.

First, I create a simple HTML form. I use the ng-model attribute again to bind data to my controller, however this time I am creating a new object - newProduct - and then following the same schema as my main data set.

This is to keep the newProduct data separate until I decide to push it to the main dataset.

  <form ng-submit="addProduct()">
  <label>Name</label>
  <input type="text" ng-model="newProduct.name"/>
  <label>Price</label>
  <input type="number" step="any" ng-model="newProduct.price"/>
  <label>For Sale</label>
  <input type="checkbox" ng-model="newProduct.forSale"/>
  <input type="submit" value="Submit" />
</form>

Helpfully Angular also has some built in form validation (try putting something other than a number in the number field), and ng-submit attribute allows me to call a function upon the form being submitted (ng-click has similar functionality, but based on a click event). The function I'm calling is below

  $scope.addProduct = function(){    
  $scope.products.push($scope.newProduct);
  $scope.newProduct = {};
};

The ng-model attribute maps the data to our JSON format, so here we just take the value of the newProduct object and 'push' it to the products array.

Then we clear the form by setting newProduct to an empty object again.

Further Reading/Watching

There are many, many more aspects to Angular - you can scale full in depth apps with it. Check out some of the links below.


9,835 7 20