Out with the old, in with the new.

A comparison of Angular 1 and 2

Created by Tony Gemoll

Bio

##Background * First used Angular 1.0.x in 2013. * Dropped it for knockout * Not a fan of Angular 1.X Why? Note: * Twist of fate, first task at NM was to write Angular 1.x ref app * IE 7 issues with angularjs * Felt less like programming in JS * and...

Because of this...


myApp.controller('MyController', ['$scope', function($scope) {
  //Thousands of lines of code
}]);
        
##Assumptions * Modern Angular 1.x Architecture * Code broken into small chucks. Maybe even components * No giant modules, controllers, views * Examples assume use of ES2015 (ES6) or Typescript
##Bootstrap Where is all begins Note: What does bootstrap mean?

Angular 1.x

Index.html





        

app.js



angular.module('app', 
[
    uiRouter,
    home.name,
    widget.name
])
.directive('app', appDirective);

        

Angular 2

Index.html



 


        

boot.js



bootstrap(App, [
    HTTP_PROVIDERS,
    ROUTER_PROVIDERS,
    APP_ROUTER_PROVIDERS
]);

        

Components

Small, possibly reusable, piece of an application's functionality.

Angular 1.x

widget.js


angular.module('widget',
    []) //dependencies
    .config(['', //string based injection
        () => { //module configurations }
    ])
    .directive('widget', widgetDirective);
        

widget.directive.js


export const widgetDirective = ()=> {
  return {
    `
`, controller, controllerAs: 'widget', ... }; };

Angular 1.x continued...

widget.controller.js


class WidgetController {    
    constructor(foo) {
        this.foo = foo;
    }

    widgetMethod(str) {
        this.foo.bar(str);
    }
}
WidgetController.$inject = ['Foo']; //string based injection.
export {WidgetController};
        

Angular 2

widget.js


@Component({
    selector: 'widget',
    template: `
`, directives: [], providers: [Foo] }) export class WidgetComponent { constructor(private foo: Foo) { } widgetMethod(str: string) { this.foo.bar(str); } }

Binding and Directives

https://angular.io/docs/ts/latest/cookbook/a1-a2-quick-reference.html

Angular 1.x



input value: {{vm.inputValue | uppercase}}

Angular 2



input value: {{inputValue | uppercase}}
####Let's talk about $scope * $scope.$apply() was fun, wasn't it? * $scope.$watch() * Angular 2 dropped all that in favor of zone.js * A Zone is an execution context that persists across async tasks. You can think of it as thread-local storage for JavaScript VMs [https://www.youtube.com/watch?v=3IqtmUscE_U](https://www.youtube.com/watch?v=3IqtmUscE_U) Note: * $watch started to get slow if a lot of bindings. * $apply was needed on async. * When in doubt $scope.$apply();

Services

Where the logic happens

Angular 1.x

widget.js


myModule.service('widgetService', WidgetService);
or
myModule.factory('widgetFactory', WidgetService);
or
myModule.provider('widgetProvider', WidgetService);
        

widget.service.js


class WidgetService  {
     constructor($http) {
        this.$http = $http;        
     }

     getWidget() {
        //return some widgets
     }
}

WidgetService.$inject = ['$http']; //string based injection
export {WidgetService};
        

Angular 2

widget.service.js


@Injectable()
export class WidgetService {
    constructor(private http: Http){

    }
    
    getWidget() {

    }
}
        

Routing

Where is that component anyways?

Angular 1.x

widget.js

Assumes use of ui-router


export const peopleSearch = angular.module('widget',
    [uiRouter]) 
    .config(['$stateProvider', 
        ($stateProvider) => {
            $stateProvider
                .state('widget', { 
                    url: '/widget/', 
                    template: '' 
                })
                .state('widgetWithParameter', { 
                    url: '/widget/:aParameter', 
                    template: '' 
                });
    }])
        

Angular 2

app.routes.js


export const routes: RouterConfig = [
  { path: 'widget', component: WidgetComponent },
  { path: 'widget/:aParameter', component: WidgetComponent },
];

export const APP_ROUTER_PROVIDERS = [
  provideRouter(routes)
];
        

boot.js


import { APP_ROUTER_PROVIDERS } from './app.routes';
bootstrap(AppComponent, [
  APP_ROUTER_PROVIDERS
])
        

href

Angular 1.x


Widget!

    Widget with foo!

    

Angular 2


Widget!
Widget with foo!
    

The new stuff

##Typescript * Types * Compile time checks * ES6+ * Decorators * @Component() * @Injectable() * **The tooling!!!** Note: * Angular 2, RxJS 5.x, and ngrx/store are all written in typescript. * Intellisense that actually works. * Formating * Smart updates from Angular 2

Errors

https://github.com/Microsoft/TypeScript-Sublime-Plugin/blob/master/screenshots/

Renaming

https://github.com/Microsoft/TypeScript-Sublime-Plugin/blob/master/screenshots/

##Redux * Not just a React lib anymore * Single immutable store * Unidirectional flow * Centralized state https://github.com/ngrx/store https://egghead.io/courses/getting-started-with-redux Note: Why? * As component trees bigger, data access because a problem. * gobal data store makes sense.
##RxJS * Hard dependency in Angular 2 * Router, http, ngrx/store, all return observables * Powerful How would you write an auto complete in JS?

Auto Complete


var keyup = Rx.Observable.fromEvent($input, 'keyup')
    .map(function (e) {
        return e.target.value;
    })
    .filter(function (text) {
        return text.length > 2;
    })
    .debounce(750)
    .distinctUntilChanged()
    .flatMapLatest(searchWikipedia) //ajax call to get data
    .subscribe((data) => { //put in DOM here } );
    

https://github.com/Reactive-Extensions/RxJS/blob/master/examples/autocomplete/autocomplete.js

##Final Thoughts * Performance? * Upgrade path from Angular 1.x? * Production ready?

But what about react?