Wednesday, August 7, 2013

Getting Started With Angular

Obviously the first thing you need to do to get started is to download Angular.js from http://code.angularjs.org/.  Let’s create a simple page with a script and index.html file.  The first thing we are going to do is define our UI.  What we are going to display is a parent entity (Sun) and a list of all of the orbiting bodies (planets and pluto). 

<!DOCTYPE html>
<html ng-app='solarSystemApp'>
    <head>
        <script src='angular.js' ></script>
        <script src='index.html.js' ></script>
    </head>
    <body ng-controller='orbitController'>
        <h1>{{parentObject.Name}}</h1>
        <h3>Orbiting Objects</h3>
        <ul>
            <li ng-repeat="object in parentObject.Children">
                <div>{{object.Name + ' - ' +  object.Type}}</div>
 <div><input type='text' ng-model="object.Type" /></div>
            </li>
        </ul>
    </body>
</html>

Here is a breakdown of the highlighted parts:
  •  ng-app=’solarSystemApp’ => This defines an angular application.  You don’t need to specify a name, but when you actually write your own app you will most likely want to.
  •  ng-controller=’orbitController’ => This defines the controller to use for the nested elements below. 
  • {{parentObject.Name}} => This displays the Name property of the parentObject property.  This is defined in the $scope object of the orbitController.
  •  ng-repeat=”object in parentObject.Children” => This will loop over every value in the Children array and apply the nested template to the value. 
  • {{object.Name + ‘-‘ + object.Type}} => This is a calculated field.  The output should be a concatenation of Name & Type.  You can also perform calculations and other operations here.
  • ng-model=”object.Type” => We are defining a two way binding here on the input text field.  The value is now bound to object.Type and will automatically update the object.Type and fields that bind to it (like the previous calculated field).  It will in real time, and not when you lose focus to the field.

Now let’s write the JS to populate this.  Although the samples on Angular don’t have some of the boiler plate stuff initially, I added it to show you what the app should look like if you were doing it for real and not just for a quick demo. 

angular.module('solarSystemApp.service', []);

angular.module('solarSystemApp.directive', []);
 
angular.module('solarSystemApp.filter', []);

angular.module('solarSystemApp', ['solarSystemApp.service', 'solarSystemApp.directive', 'solarSystemApp.filter']).
  run(function () {
      // This is effectively part of the main method initialization code
     
  });

app.controller('orbitController', ['$scope', function orbitController(scope){
    scope.parentObject = {Name: 'Sun', Type: 'Star',
        Children: [{Name: 'Mercury', Type: 'Planet'}, {Name: 'Venus', Type: 'Planet' },
            {Name: 'Earth', Type: 'Planet'}, {Name: 'Mars', Type: 'Planet'},
            {Name: 'Jupiter', Type: 'Planet'}, {Name:'Saturn', Type: 'Planet'},
            {Name: 'Uranus', Type: 'Planet'}, {Name: 'Neptune', Type: 'Planet'},
            {Name: 'Pluto', Type: 'Dwarf Planet'}]};
}]);

Here is a quick breakdown of the code.
  • angular.module('solarSystemApp.service', []); => We are creating a module called solarSystemApp.service.  If you have service calls in your code (which you probably do), you would add them here.
  • angular.module('solarSystemApp.directive', []); => We are creating a module called solarSystemApp.directive.  We would add any directives that we write here.
  •  angular.module(‘solarSystemApp.filter’, []); => This is where we add filters.  A common use for filters is to translate a value into another one for display purposes.  There are some built in ones like uppercase, and date formats.
  • angular.module('solarSystemApp', … => This is where you would put any initialization code for your app. 
  • app.controller(‘orbitController’, .. => This is the code for the controller.  In this code we add our models (hardcoded) to the scope and that will allow binding to the UI components. 


There are some really cool things to note here.  You don’t need to wrap my data in anything such as Observable or Observable array to enable 2 way binding.  Objects and arrays that are properties of the object attached to the scope are valid for binding.  Thus the scope traverses the entire object to know what you can bind to.   I can also still write my code in separate files and reference them separately or join them together using a js file merge tool.  It also allows you to decouple your JS code such as your service and model code from angular.  That kind of decoupling allows for unit testing, and the ability to integrate angular easily into your current JS style.


No comments:

Post a Comment