Rules to Better AngularJS

​UPDATE (Jan 2016): Angular 2 is now ready for production applications so you should consider using Angular 2 instead. Check out our Rules to Better Angular 2 for more info.

Hold on a second! How would you like to view this content?
Just the title! A brief blurb! Gimme everything!
AngularJS is a powerful and elegant front-end javascript framework. It is designed to make highly interactive front-end designs.
  1. Do you know the best Visual Studio Extensions and NuGet Packages for AngularJS?

    Following this rule will ensure the right NuGet packages and Visual Studio Extensions are included in your projects to help speed up your development, follow best practices and have the team using the same processes

    The best NuGet packages are:
    • Angular.UI.Bootstrap 
      Check out the whole suite of tools from the Angular UI team.​
    • AngularJS.Core
      This core package only has the minimum Angular references to get started. Other Angular packages like AngularJS.Route can be added as needed in addition to this.

    • AngularJS 
      The whole AngularJS library.

    • HotTowel.Angular 
      John Papa's popular AngularJS Single Page Application (SPA) template.

    e:
    • Side Waffle
      Templates for common AngularJS components like controllers, factories, and modules.
    • Web Essentials
      While not AngularJS specific, this Visual Studio extension is a must have for any web development.

    Alternate sources for Angular Modules:
    • NgModules.org
      A source for all popular AngularJS modules that can be sorted by popularity.

  2. Do you write your Angular 1.x directives in TypeScript?

    ​​​​​​​​​​​​​​Angular 1.x directives are awesome and they help you reuse your code base by being able to drop directives (aka reuasable HTML elements) into several pages without having to duplicate your code base.​

    Writing your AngularJS 1.x directives in Typescript will help in the following ways:

    1. ​You will more easily migrate to Angular2 which is written in TypeScript
    2. Your code will be more robust with compile time checking avoiding errors you might miss or not see till you run the application in the browser.
    3. You can more easily manage your code by reusing directives and not duplicating code.
    4. If you keep your DDO (Directive Definition Object) seperate to your directive controller logic you can avoid using $scope and further be ready to migrate to Angular2. You can also reuse the directive controller with other parts of your application. 

    Writing Angular 1.x directives in Typescript can be a challenge with only a few examples available online. Most examples of Angular 1.x directives are in JavaScript and converting them to TypeScript versions means you need to have a good understanding of how it all works. Many examples that are available online do it a little differently from each other. 

    ​​HTML

    ​​​<current-value></current-value​>

    ​Typescript

       module app.widgets {
        'use strict';
    
        class CurrentValueDirectiveController {
            amount: number;
    
            static $inject = ['investmentReportsService'];
            constructor(private investmentReportsService: app.dataServices.InvestmentService) {
            }
    
            setCurrentValue() {
                this.investmentReportsService.investmentSummary(this.amount)
                    .then((response) => {
                        this.currentValue = response.Data.TotalMarket;
                    });
            }
        }​
    
        function CurrentValueDirective(): ng.IDirective {
            return {
                restrict = 'E';
                templateUrl = 'app/widgets/currentValue/currentValue.directive.html';
                controller = CurrentValueDirectiveController;
                controllerAs = 'currentValueDirCtrl';
                bindToController = true;
                scope = {
                    amount: '='
                }
            }
        }
    
        angular
            .module('app.widgets')
            .directive('currentValue', CurrentValueDirective);
    }​
    

    ​​

  3. Do you name your dependencies to avoid problems with minification?

    ​Angular uses parameter names to determine which dependencies to inject. When you minify your angular code, the parameter names are changed, so you must name your dependencies to ensure they work correctly.


    The standard way to inject your dependencies looks a little like the following. We're defining a controller in this case.
    phonecatApp.controller('PhoneListCtrl', function ($scope, $http) {...}
    Bad Example: This code will break when minified

    When this code is minified the parameters are renamed. This means that the dependency injector no longer knows which services to inject.

    You can fix this in two ways. The first one uses the $inject property to identify the name of the parameters in order:
    function PhoneListCtrl($scope, $http) {...}
    PhoneListCtrl.$inject = ['$scope', '$http'];
    phonecatApp.controller('PhoneListCtrl', PhoneListCtrl);
    Good Example: This code names the parameters using the $inject property

    The second and preferred option is to pass an array containing the names, followed by the function itself. Take a look:
    phonecatApp.controller('PhoneListCtrl', ['$scope', '$http', function($scope, $http) {...}]);
    Better Example: This code names the parameters inline which is a little cleaner​

    Using this method will ensure you don't run into problems with minification. If you'd like to read more, check out the Angular tutorial for ​Dependency Injection​.​​
  4. Do you consider SEO in your AngularJS application?

    ​​​​​​​​Search Engine Optimisation (SEO) with a Single Page Application (SPA) needs consideration like any other Framework to ensure it is SEO friendly. Becuase AngularJS manages your routing and URLs it is important to be aware of the differences in making an AngularJS SPA SEO friendly.

    If you ignore your SEO in an Angular SPA you may not have your pages indexed by Google and lose your ranking with SEO. If your pages are not being rendered to Googles bots when they crawl your site, Google can not see your pages and it is like they do not exist.

    The only way to be sure your Angular SPA will be crawled and indexed properly by Google Bots is to intercept all their requests and serve them HTML you pre-render on the server. 

    It is not enough to just use hashes in your URLs (e.g., www.example.com/index.html#mystate, where #mystate is the hash fragment) or hope Google can crawl and Angular application correctly. You can read more here Guide to AJAX crawlin g for webmasters and developers.  There are several libraries to help pre-render your code available on the internet. 
    If you do not pre-render HTML you may still get good enough SEO as Google Bots are getting better at crawling JavaScript but you can not be certain it will work. You can use Google Fetch to test how your web pages look to a Google bot.
    seo_for_angular-diagram.png
    Figure: How to configure your site to pre-render HTML for Google bots.

    Besides pre-rendering HTML to get your AngularJS Single Page Application (SPA) SEO friendly you can apply the following practices:

    1. Enable html5Mode for AngularJS outing
      This will remove the hashtagged-URLs by default for pretty URLS, using the pushState feature that newer browsers have, which still falls back to the hashbang method if pushState isn't available. To enable html5Mode in AngularJs read more scotch.io
    2. Creating a sitemap
      Web crawlers usually discover pages from links within the site and from other sites. Sitemaps supplement this data to allow crawlers that support Sitemaps to pick up all URLs in the Sitemap and learn about those URLs using the associated metadata. Using the Sitemap protocol does not guarantee that web pages are included in search engines, but provides hints for web crawlers to do a better job of crawling your site.  More information at sitemap.org 
    3. Enriching your app with meta information
      This step ensures your search results are represented in a meaningful and predictable way. Dynamically changing the meta tags content in the head section of the page can also help google find and represent you in their search results.  
      For more information and a demo see this blog: weluse.de
    4. You can inspect what HTML Google renders with Webmaster Tools, it is also an excellent source of information.
    5. Here’s what you need to know to ensure your website is crawled correctly by Google in general regardless of if your application is a SPA: Introduction to SEO and Google Tools – Craig Bailey [FireBootCamp]
      ​​

    Note: Since May 2014 Google announced that they're finally crawling javascript making SEO for a SPA simpler. Previously your SPA needed to distinguish between normal users and crawlers - and re-route (somehow) to the special crawler-only-endpoints if a bot is requesting the page.(source: http://googlewebmastercentral.blogspot.de/2014/05/understanding-web-pages-better.html)

  5. Do you call AngularJS services from your Kendo datasource?

    To keep a good separation of concerns between your AngularJS controllers and your data service layers you should always call an AngularJS service or factory from your Kendo datasource logic.

    Many demonstrations show a hard coded string in your Angular controllers calling your API but this means you will be making data API calls from your controllers, which is bad for several reasons:

    1. You will end up with many API data calls from different controllers versus all being in your one location
    2. Your controllers will be harder to unit test
    3. If you want to call the same API endpoint somewhere else in your application you now have two place with this hard coded string, that might need to change in the future
    4. If you keep all your data calls in one place your code will be easier to read and you can share business logic for making the API calls within your Angular service or factory, like a common error handling message for failed API calls
    5. Finally you can perform actions while the promise is being resolved, like show a spinner animation or log out a message to the user

    The bad way to call your API from a Kendo datasource with AngularJS. Notice the hard coded url directly calling the API endpoint.

    read: {​ 
    url: "../content/dataviz/js/spain-electricity.json",
    dataType: "json"
    } ​​
    Bad Example -​ This hard codes your url endpoint throughout your application ​​

    This is example is in TypeScript and you can see the Kendo data source is calling the getFundAssetPositionChartData function and passing it a promise which when resolved will return the data. This function calls an AngularJS service which then calls the API endpoint. You can also see in the getFundAssetPositionChartData function the ‘this.isLoading = true’ code which is turning the pages spinner feature on and off when the call is resolved, to let the user know it is processing.​​​

    module app.widgets {
        'use strict';

        class AssetAllocationByAssetClassChartController {
            isLoading: any;
            static $inject = ['app.dataServices.InvestmentReportsService']
            constructor(private investmentReportsService: dataServices.InvestmentReportsService) { }

            options = {
                series: [{
                    field: 'AssetStrategyOverallPercent',
                    categoryField: 'AssetClassName'
                }],
                seriesDefaults: {
                    type: 'pie'
                },
                legend: {
                    position: 'bottom',
                    labels: {
                        visible: true,
                        background: 'transparent',
                        template: '#=text # #=value#% '
                    }
                },
                dataSource: new kendo.data.DataSource({
                    transport: {
                        read: (promise: any) => {
                            this.getFundAssetPositionChartData(promise);
                        }
                    }
                })
            }
            getFundAssetPositionChartData = (promise) => {
                this.isLoading = true;
                return this.investmentReportsService.fundAssetPosition()
                    .then((response) => {
                        promise.success(
                            response.Data.PortfolioAssetPositions[0].AssetClassDetailList
                        );
                        this.isLoading = false;
                    });
            }
        }
        Angular.
            .module('app.widgets')
            .controller('app.widgets.assetAllocationByAssetClassChartController',
            AssetAllocationByAssetClassChartController
            )
    }​​​

    Good Example - This code passes a promise to a function which calls an AngularJS service to call the API endpoint.​
  6. Angular - Do you know the stuff to install?

    It is suggested using cli.angular.io to start an Angular2 project especially when learning as it is the easiest way to both get started and also follow best practices.

    If you are new to Angular we recommend you use VSCode versus Visual Studio 2015/17 as the TypeScript support and project directory (without a Visual Studio Project) is easier.

    angular-quick-start.png
    Figure: Bad example - Don 't use the Angular QuickStart because you have to setup everything manually (the CLI gives you it all automatically)
    1. Install nodejs V4 and npm V3 or higher https://nodejs.org/en
      Check you have the right versions:

       node -v
       npm -v
       npm -g ls --depth=0

      Note: If you do not have the right version of node or npm, it is best to uninstall then and reinstall them and your global npm packages. Using the second command below you can check which global npm packages you have installed so that you can reinstall them afterward.
    2. Install git https://git-scm.com Check you have git: 

      git --version

    3. Install latest Angular CLI [cli.angular.io]cli.angular.io

      Check you have the latest version:

      ng -v
      npm uninstall -g @angular/cli
      npm cache clean
      npm install -g @angular/cli

    4. Troubleshooting
      If you get node gyp errors follow instructions here https://github.com/nodejs/node-gyp
      If you get permission errors follow instructions here https://docs.npmjs.com/getting-started/fixing-npm-permissions  

    5. We recommend if you do not have a great TypeScript enabled IDE yet that you use http://code.visualstudio.com

  7. Do you know the best free resources for AngularJS

  8. Do you know the best sample applications?

    Before starting a software project and evaluating a new technology, it is important to know what the best practices are. The easiest way to get up and running is by looking at a sample application. Below are a list of sample applications that we’ve curated and given our seal of approval.

    SQL Server (2014 and below)

    SQL Server 2016 and Azure SQL Database

    ASP.NET MVC + WebAPI

    SPA

    AngularJS

    Angular

  9. Do you understand that with Angular you read and write to the model... never to the page? (a.k.a. Forget about jQuery)

    ​The most common mistake that developers make when moving from jQuery to Angular is that they continue to think about updating the page.

    understand-jquery.png
    Figure: In jQuery, you design a page and then use jQuery to perform interactions with the page e.g. reading and setting the values of input boxes, updating the content of divs or handling button events
    understand-badcode.png
    Figure: Bad Example - using jQuery on Angular views will lead to worlds of pain

    A fundamental principal of Angular is that you build a Model in JavaScript (or TypeScript) and then on your view you just databind your UI elements to the model. Any changes that are made are made to the model and the view updates automatically.

    In Angular, you do not interact with the page you update the model, and the page is just displaying a view of the model.

    understand-goodcode.png
    Figure: Good Example - In both AngularJs & Angular 2.0 jQuery is not required on the view. The view binds to properties on a JavaScript model

    Further reading: http://stackoverflow.com/questions/14994391/thinking-in-angularjs-if-i-have-a-jquery-background