Monday, May 18, 2015

Week 8 - Promises

This week we will wrap up this series with the topic of promises (for some reason it took me awhile to get used to using this pattern; thus saving it for last).

Assignment
Fork the fiddle "AngularJS: A Walk-Through - Week 7" and
  • Name it "AngularJS: A Walk-Through - Week 8"
  • "Update" it and "Set as base". 

Assignment
Read articles describing promises; in particular:

JavaScript Promises and AngularJS $q Service
<http://www.webdeveasy.com/javascript-promises-and-angularjs-q-service/>

In order to demonstrate the $q service, we will refactor our gemService. First we refactor it so that has a query function with success and error callbacks (throwing in a 2 second timeout to introduce an asynchronous element).

JavaScript
 
// store/gems.service.js
(function() {
    angular
        .module('storeModule')
        .factory('gemsService', gemsService);
    /**
    * @name gemsService
    * @desc Service for gems.
    */
    gemsService.$inject = ['$timeout'];
    function gemsService($timeout) {
        var service = {};
        service.query = query;
        var gems = [{
            name: 'Azurite',
            // OBMITTED
            reviews: []
        }];
        return service;
        function query(success, error) {
            $timeout(function() {
                success(gems);
            }, 2000);    
        }
    }
})();   

With the new gemService, the StoreController is changed to:

JavaScript
 
// store/store.controller.js
(function() {
    angular
        .module('storeModule')
        .controller('StoreController', StoreController);
    /**
    * @name StoreController
    * @desc Controller for the store screen.
    */
    StoreController.$inject = ['gemsService'];
    function StoreController(gemsService) {
        var vm = this;
        gemsService.query(function(gems) {
            vm.products = gems;
        }, function() {
        });
    }
})();  

Now that we have a typical asynchronous function, we will rewrite the query function as follows with the $q service.

JavaScript
 
// store/gems.service.js
(function() {
    angular
        .module('storeModule')
        .factory('gemsService', gemsService);
    /**
    * @name gemsService
    * @desc Service for gems.
    */
    gemsService.$inject = ['$timeout'];
    function gemsService($timeout) {
        var service = {};
        service.query = query;
        var gems = [{
            name: 'Azurite',
            // OBMITTED
            reviews: []
        }];
        return service;
        function query() {
            var deferred = $q.defer();
            $timeout(function() {
                deferred.resolve(gems);
            }, 2000);
            return deferred.promise;
        }
    }
})();   

And now we implement the promise in the StoreController.

JavaScript
 
// store/store.controller.js
(function() {
    angular
        .module('storeModule')
        .controller('StoreController', StoreController);
    /**
    * @name StoreController
    * @desc Controller for the store screen.
    */
    StoreController.$inject = ['gemsService'];
    function StoreController(gemsService) {
        var vm = this;
        gemsService.query().then(function(gems) {
            vm.products = gems;
        });
    }
})();

Assignment
Using the information above, refactor this week's fiddle to use the $q service.

Sample of Week Result
The result of this week is an AngularJS app, "AngularJS: A Walk-Through - Week 8".

AngularJS: A Walk-Through - Week 8
<https://jsfiddle.net/sckmkny/e5LLpygs/>

Bonus
Now that one understands promises, the last refinement would be to change up the app so that the promises are resolved before loading the screen (to avoid showing the screen partially complete).  The key here is to AngularJS Route Resolves.

Using Resolves In AngularJS Routes
<http://odetocode.com/blogs/scott/archive/2014/05/20/using-resolve-in-angularjs-routes.aspx>

Saturday, May 9, 2015

Week 7 - Style Guides (Continued)

This week we will continue to refactor our code based on the opinionated style guide by Todd Moto.

Assignment
Fork the fiddle "AngularJS: A Walk-Through - Week 6" and
  • Name it "AngularJS: A Walk-Through - Week 7"
  • "Update" it and "Set as base". 

Assignment
Read through the last sections (starting from Filters) of the following style guide and apply fixes to the fiddle.  Some of the techniques are more advanced and thus not used in our simple example.

AngularJS StyleGuide by Todd Motto
<https://github.com/toddmotto/angularjs-styleguide>

Hints:
  • Routing resolves / Promises: We will address promises in a later week.
  • Performance / One-time binding syntax: Go through app to look for opportunities to use this feature.
  • Comment standards / jsDoc: Add some simple documentation to your app.

Assignment
Todd Motto suggests reading through another style guide; most of the ideas are duplicated.  Apply what is relevant.

angular-styleguide by John Papa
<https://github.com/johnpapa/angular-styleguide>

Hints:
  • Bindable Members Up Top (Y033) - Do it.
  • Manually Identify Dependencies (Y091) - Do it.
  • Routing (Y270) - Not using AngularJS Router in this example
  • Routing (Y271) - Move routing into separate files, e.g.
    • app.routes.js
    • marketing/marketing.routes.js
    • marketing/store.routes.js

Sample of Week Result
The result of this week is an AngularJS app, "AngularJS: A Walk-Through - Week 7" that will be used as a starting point for the next week.

AngularJS: A Walk-Through - Week 7
<http://jsfiddle.net/sckmkny/n1v22jjs/>

Sunday, May 3, 2015

Week 6 - Style Guide

This week we will refactor our code based on an opinionated style guide by Todd Moto that was suggested during the keynote speech of the ng-conf 2015 conference (AngularJS conference).  The main benefits of applying the style guide will be to make the code more supportable over the long-term.

note: Originally, was going to do this in one week, but due to the amount of changes, opted to break it into two.  Also, this week is a little different as it has less guidance (might require one to "cheat" and review the final result).

Assignment
Fork the fiddle "AngularJS: A Walk-Through - Week 5" and
  • Name it "AngularJS: A Walk-Through - Week 6"
  • "Update" it and "Set as base". 

Assignment
First, we are going follow a different (small) guide as to how to organize code into modules (and folders / files):

Code Organization in Large AngularJS and JavaScript Applications
<http://cliffmeyers.com/blog/2013/4/21/code-organization-angularjs-javascript>

Re-organize the fiddle into three modules (and folders / files) with each component in a separate file:
  • app
  • marketing (for the about components)
  • store (for the store components)
The final file structure (remember, we are using comments to delineate files in JSFIDDLE) ends up being:
  • app.js
  • index.html
  • marketing
    • about.controller.js
    • about.html
    • marketing.module.js
  • store
    • gems.services.js
    • product-description.directive.js
    • product-description.html
    • product-gallery.directive.js
    • product-gallery.html
    • product-reviews.directive.js
    • product-reviews.html
    • product-specs.directive.js
    • product-spec.html
    • product-tabs.directive.js
    • product-tabs.html
    • store.controller.js
    • store.html
    • store.module.js

Assignment
Read through the first four sections (Modules - Directives) of the following style guide and apply fixes to the fiddle.

AngularJS StyleGuide by Todd Motto
<https://github.com/toddmotto/angularjs-styleguide>

Hints:
  • Modules / Definitions: One will need to change up the fiddle to not use the setting and getter syntax.
  • Modules / Methods: One will need to change up the fiddle to pass functions into modules (rather than anonymous function callbacks).
  • Controllers / controllerAs syntax: Not much to do here as we did not use the older AngularJS binding with "$scope".  But, we do want consistent and unique names (instead of just "vm") in the "controllerAs" syntax; recommend something like "StoreController as storeVM".
  • Controllers / controllerAs 'vm': Need to use "vm" to capture the "this" context.
  •  Some other conventions to consider:
    • Modules are named lowerCamelCase.
    • Controllers are named UpperCamelCase (as they are constructors).
    • Factories are named lowerCamelCase.
    • Directives are named lowerCamelCase.

Sample of Week Result
The result of this week is an AngularJS app, "AngularJS: A Walk-Through - Week 6" that will be used as a starting point for the next week.

AngularJS: A Walk-Through - Week 6
<http://jsfiddle.net/sckmkny/xqy23z1e/>

Saturday, April 25, 2015

Week 5 - Customized Services and Routes

This week we are going to revisit services (Code School just touched upon them) and introduce routes (used as one expands the app to use multiple screens).

Assignment
Fork the fiddle "AngularJS: A Walk-Through - Week 4" and
  • Name it "AngularJS: A Walk-Through - Week 5"
  • "Update" it and "Set as base". 

Services

In the example we have been using, the gems data was simply jammed into our controller; not pretty and not reusable. We are going data off into a separate object called a service.

Assignment
Read articles describing AngularJS services; in particular:

AngularJS Developers Guide: Services
<https://docs.angularjs.org/guide/services>

If one read other articles on services, they would have likely bumped in a number of other types of services other than a factory, e.g., service and provider.  Yes, it is unfortunate they they used the word service to mean two different things.  The good news is that for the most part these others are either redundant or used in edge cases.  We will not use them.

First, we are going to stub out a gems service (to be added to ends of the JSFIDDLE JavaScript pane).

JavaScript
// gems.js
(function() {
var app = angular.module('store-services', []);
    app.factory('gems', function() {
        var service = {};
        return service;
    });
})();

Next we are going to have the "gemStore" app use the "store-services" by updating the following at the top of the JSFIDDLE JavaScript.

JavaScript
    var app = angular.module('gemStore', ['store-directives', 'store-services']);

Next we are going to move the "gems" definition  out of the "StoreController" and into the "gems" service by simply replacing the empty object "{}" with the array of gems.

Finally, we are going to inject the "gems" service into the "StoreController" as follows:

JavaScript
    app.controller('StoreController', ['gems', function(gems){
        this.products = gems;
    }]);

Assignment
Replicate the work above in the fiddle "AngularJS: A Walk-Through - Week 5" ("Update and "Set as base")

As one can see, this did not add any functionality; rather this set us up to use the "gems" service in other parts of this application.

Assignment
While this was covered a bit in the Code School material and we just used it above, read articles on AngularJS dependency injection; in particular:

AngularJS Developers Guide: Dependency Injection
<https://docs.angularjs.org/guide/di>

Routing

Angular uses different hash URLs, e.g., <http://domain.com/#/> and <http://domain.com/#/login> to differentiate screens as one navigates the app.  Like any URL they can be bookmarked and crawled independently by the search engines. The important thing to understand is that the browser is not reloading the page as it navigates to a different hash URL.

Angular uses a separate ngRoute module to handle navigation between screens within an app.

Assignment
Read articles on AngularJS routing; in particular:

AngularJS: Tutorial: 7 - Routing & Multiple Views
<https://docs.angularjs.org/tutorial/step_07>

We are going to simply use the ngRoute module with the existing functionality (still only one screen). We first install the ngRoute module from a CDN using JSFIDDLE "External Resources".

//ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular-route.js

Then we make the "gemStore" application depend on ngRoute.

JavaScript
 
var app = angular.module('gemStore', ['ngRoute', 'store-directives', 'store-services']);

We then add an app.config to the gemStore application:

JavaScript
 
    app.config(['$routeProvider', function($routeProvider) {
        $routeProvider.
        when('/', {
            templateUrl: 'store.html',
            controller: 'StoreController'
        }).
        otherwise({
            redirectTo: '/'
        });
    }]);        


Then we move the HTML (the top part that is not part of a ng-template script section) into the "store.html" file using the ng-template syntax.

HTML
 
<script id="store.html" type="text/ng-template">

Finally, we insert the ngView directive to the top of the HTML.

HTML
 
<div ng-view></div>

Assignment
Replicate the work above in the fiddle "AngularJS: A Walk-Through - Week 5" ("Update and "Set as base")

As one can see, this did not add any functionality; rather this set us up to add additional screens.

Assignment
This challenging assignment is to use what one knows to add an "about.html" page that is linked from the "store.html" page.  Things to remember:
  • Add the appropriate routing entries to the "app.config" section, e.g. "about.html" and "AboutController".
  • Create a do nothing "AboutController".
  • Create the "about.html" page using the ng-template syntax.
  • Use a hash URL to link between pages.

Sample of Week Result
The result of this week is an AngularJS app, "AngularJS: A Walk-Through - Week 5" that will be used as a starting point for the next week.

AngularJS: A Walk-Through - Week 5
<http://jsfiddle.net/sckmkny/y04ht4mt/>

Saturday, April 18, 2015

Week 4 - Shaping Up with Angular.JS by Code School

This week we are going to wrap up the "Shaping Up with Angular.JS" by Code School course.

Much of the work this week involves refactoring the existing code into separate directives and then grouping them into modules.

Assignment
Fork the fiddle "AngularJS: A Walk-Through - Week 3" and
  • Name it "AngularJS: A Walk-Through - Week 4"
  • "Update" it and "Set as base". 

Assignment
Complete the levels
  • Level 4: Custom Directives
  • Level 5: Services

    Assignment
    As one completes the challenge "5.2 Refactoring into a Module", replicate the solution in the fiddle "AngularJS: A Walk-Through - Week 4" ("Update and "Set as base") . Some things to keep in mind:

    note: Notice that we are replicating 5.2 and not the last challenge.  This is because we will do our own example of a service in a later week.

    • Remember the ng-app and the "StoreController" ng-controller directives are in the body tag accessible from the "Fiddle Options"; so one only needs to copy the content of the body tag to the JSFIDDLE HTML panel.
    • Because JSFIDDLE does not support multiple files, we are going to need to build both the app.js and the products.js in the JAVASCRIPT panel; just copy and past them one after the other.
    • Similarly, we will need to build all the separate HTML files into the single HTML panel. Luckily AngularJS provide a mechanism to simulate separate HTML template files by wrapping the HTML with filename "FILENAME" with the "<script type="text/ng-template" id="FILENAME">" and "</script>" tags.
    • Repeat the inclusion each of the templates below the index.html content, e.g.,
      • product-description.html
      • product-specs.html
      • product-reviews.html
      • product-tabs.html
      • product-gallery.html
    • Remember to fix the images in the gems object with the prefix:
      http://dhg7upb7j7jqa.cloudfront.net/shaping_up_with_angular_js/assets/demo/

    One oddity in the solution to the 5.2 challenge above is that they encapsulated the controller in the productsTabs directive but not the productReviews directive.  We will fix that.

    Assignment
    Move the functionality of the "ReviewController" into the "productReviews" directive.
    1. Create both "controller" and "controllerAs" properties of the "productsReviews" directive.
    2. Set the value of the controller to be the anonymous function of the "ReviewController".
    3. Set the value of the "controllerAs" to be "reviewCtrl" (in this case, include the double quotes")
    4. Delete the ReviewController definition.
    5. Delete the "ng-controller" directive from the form with name "reviewForm".

    Sample of Week Result
    The result of this week is an AngularJS app, "AngularJS: A Walk-Through - Week 4" that will be used as a starting point for the next week.

    AngularJS: A Walk-Through - Week 4
    <http://jsfiddle.net/sckmkny/033hgu38/>

    Sunday, April 12, 2015

    Week 3 - Shaping Up with Angular.JS by Code School

    This week we are going to do only one Code School level (Level 3: Forms) to allow some folks to catch up from last week.

    One interesting observation to make as one looks over the resultant application from this week's work is just how little JavaScript (approx. 30 lines outside of the embedded data) is needed for the functionality provided.

    Assignment
    Fork the fiddle "AngularJS: A Walk-Through - Week 2" and
    • Name it "AngularJS: A Walk-Through - Week 3"
    • "Update" it and "Set as base". 

    Assignment
    Complete the level
    • Level 3: Forms

    Assignment
    As one completes the final challenge "3.10 Form Styling", replicate the solution in the fiddle "AngularJS: A Walk-Through - Week 3" ("Update and "Set as base") . Some things to keep in mind:

    note: Notice that we are replicating 3.10 and not 3.11 (the last challenge).  This is because the Code School folks neglected to build 3.11 on top of 3.10.
    • Remember the ng-app and the "StoreController" ng-controller directives are in the body tag accessible from the "Fiddle Options"; so one only needs to copy the content of the body tag to the JSFIDDLE HTML panel.
    • Remember we are going to simply insert the app.js JavaScript in JSFIDDLE by copying it into the "JavaScript" panel.
    • Remember to fix the images in the gems object with the prefix:
      http://dhg7upb7j7jqa.cloudfront.net/shaping_up_with_angular_js/assets/demo/

    Assignment
    We are going to update our JSFIDDLE to implement the created on date as done in "3.11 Showing CreatedOn Date".

    note: Remember; one cannot simply copy the entire HTML and JavaScript as Code School neglected to build 3.11 on top of 3.10.

    Apply the three objectives of "3.11 Showing CreatedOn Date" to the JSFIDDLE example.

    Sample of Week Result
    The result of this week is an AngularJS app, "AngularJS: A Walk-Through - Week 3" that will be used as a starting point for the next week.

    AngularJS: A Walk-Through - Week 3
    <http://jsfiddle.net/sckmkny/nhsk8npu/>

    Sunday, April 5, 2015

    Week 2 - Shaping Up with Angular.JS by Code School

    This week we are going to learn the basics of AngularJS.

    Assignment
    Fork the fiddle "AngularJS: A Walk-Through - Week 1" and
    • Name it "AngularJS: A Walk-Through - Week 2".
    • In "External Resources" add Bootstrap 3.1.1 from the following CDN
    <//dhg7upb7j7jqa.cloudfront.net/shaping_up_with_angular_js/assets/demo/bootstrap.min.css>

    note: Using a newer version of Bootstrap (from a standard CDN) will introduce subtle differences from the Code School example. 
    • "Update" it and "Set as base". 

    Assignment
    Create a free account at:

    Code School 
    <http://www.codeschool.com>

    Start the course "Shaping up with Angular.js" listed under the JavaScript language path.

    Assignment
    Complete the levels
    • Level 1: Flatlander's Gem Store
    • Level 2: Built-in Directives

    Assignment
    As one completes the final challenge "2.10 Using Gallery Controller", replicate the solution in the fiddle "AngularJS: A Walk-Through - Week 2" ("Update and "Set as base") . Some things to keep in mind:
    • As JSFIDDLE does not have a mechanism to modify the HTML tag, use the "Fiddle Options":  "Body tag" setting instead, e.g.,
      <body class="list-group"  ng-app="gemStore" ng-controller="StoreController as store">
    • Instead of linking to a external JavaScript file "app.js" in the <head> as in the  Code School example (not a feature of JSFIDDLE), we are going to simply insert the JavaScript in JSFIDDLE by typing in the "JavaScript" panel.
    • To show the images, add the prefix:
      http://dhg7upb7j7jqa.cloudfront.net/shaping_up_with_angular_js/assets/demo/
      before each of the image strings.

    Sample of Week Result
    The result of this week is an AngularJS app, "AngularJS: A Walk-Through - Week 2" that will be used as a starting point for the next week.

    AngularJS: A Walk-Through - Week 2
    <http://jsfiddle.net/sckmkny/n6p5v0b9/>

    Tuesday, March 17, 2015

    Week 1 - Expectations, Prerequisites, Motivation, and Setup

    This walk-through is principally focused on introducing one to the AngularJS JavaScript Model-View-Controller (MVC) framework. It is expected that after going through this walk-through, one will be able to to build client-side applications using AngularJS and continue to learn independently.

    Meta
    Through-out this walk-through, information that is actionable, e.g., assignments, is provided inside blocks like this "Meta" block.

    Recommended; provide email address (to the right) for an email of each week's materials on Monday mornings.

    Comments (questions, tips, answers, etc.) are encouraged.

    The material is arranged to deliver about five hours of work each week; new material will be released on Monday mornings. The walk-through is expected to take six weeks.

    1. Week 1 - Expectations, Prerequisites, Motivation, and Setup
    2. Week 2 - Shaping Up with Angular.JS by Code School
    3. Week 3 - Shaping Up with Angular.JS by Code School (Continued)
    4. Week 4 - Shaping Up with Angular.JS by Code School (Continued)
    5. Week 5 - Customized Services and Routes
    6. Week 6 - Style Guides
    7. Week 7 - Style Guides (Continued)
    8. Week 8 - Promises

    Prerequisites

    It will be difficult for one to follow this walk-through without a basic understanding of HTML/CSS and JavaScript.

    While there are many resources on HTML/CSS and JavaScript available, the courses at Code School <https://www.codeschool.com> are particularly good (includes hands-on coding challenges to test one's knowledge along the way).


    What and Why Client-Side JavaScript

    Until fairly recently (several years ago), it was common to see arguments for and against client-side JavaScript; the alternative being server-side HTML rendering. Today, however, there is a growing consensus that client-side JavaScript is here to stay and will be increasingly used.

    Assignment
    Read articles comparing server-side and client-side rendering; in particular read the following:

    Server vs client side rendering (AngularJS vs server side MVC)<http://technologyconversations.com/2014/07/10/server-vs-client-side-rendering-angularjs-vs-server-side-mvc/>


    What and Why a Model-View-Controller (MVC) Framework

    The key to understanding what and why a MVC framework is to realize that building useful client-side application is inherently complicated. Using tools (like a MVC framework) provide a reusable structure to organize the code into distinct and recognizable sections.

    Assignment
    Read articles on MVC frameworks and the concept of separation of concerns (SoC); in particular read the following:

    Separation of concerns - Wikipedia, the free encylopedia
    <http://en.wikipedia.org/wiki/Separation_of_concerns>

    MVP Architecture - Google Chrome
    <https://developer.chrome.com/apps/app_frameworks>


    Why AngularJS

    First, there are a number of popular JavaScript MVC frameworks available today: Ember.js, Backbone.js, AngularJS, and the new kid on the block, React. Of these, AngularJS is the oldest (2009) and yet continues to grow in popularity.

    One active concern in the development of JavaScript MVCs is to improve the rendering performance; React differentiates itself with its virtual DOM diff implementation for ultra-high performance. AngularJS is preparing to release Angular 2 to improve performance.

    Deep Tree: Speed
    (minute 35:30) ng-conf 2015 Day 1 Keynote - Brad Green and Igor Minar



    Assignment
    Read the following:

    The Languages and Frameworks That You Should Learn in 2015 | Tutorialzine
    <http://tutorialzine.com/2014/12/the-languages-and-frameworks-that-you-should-learn-in-2015/>


    Assignment
    Watch the following (Yes, the whole 40 minutes):

    ng-conf 2015 Day 1 Keynote - Brad Green and Igor Minar
    <http://www.ng-conf.org/>


    Setup

    The examples in this walk-through will be developed in JSFIDDLE <http://jsfiddle.net/>. JSFIDDLE is a free online JavaScript IDE that allows one to quickly prototype web applications.

    Tips on Using JSFIDDLE:

    • One can create a free account to store "fiddles" (prototype web applications).
    • Name your fiddle with "Fiddle Options" and update often (use the "Set as base" to commit changes more permanently).
    • Use the "Debug on mobile" button to open up a separate tab/window to allow for easier debugging in the browser.
    • Fiddle setup for this walk-through:
      • Leave the JavaScript library as "No-Library (pure JS)"
      • Set the JavaScript to load with "No wrap - in <head>".
      • In "External Resources" add AngularJS 1.3.9 from the following CDN:
        <//ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js>

        note: notice the missing http: or https: (this allows the browser to choose the protocol based on the protocol of the calling HTML page).

    Assignment
    Setup a JSFIDDLE <http://jsfiddle.net/> account and orient oneself to its use.

    Create a new fiddle:
    • Name it "AngularJS: A Walk-Through - Week 1"
    • Set it up as described for this walk-through (above).

    Sample of Week Result
    The result of this week is do nothing fiddle named "AngularJS: A Walk-Through - Week 1" that will be used as a starting point for the next week.

    AngularJS: A Walk-Through - Week 1
    <http://jsfiddle.net/sckmkny/dm02pd0s/>