Angular 1 meets Angular 2
ng-conf 2015
How can we prepare for Angular 2?
So I have an Angular 1 app...
The best thing you can do to get ready is follow best practices.
Hello, ES6!
Migrating your code to ES6 is easier than you think.
var babel = require('gulp-babel');
gulp.task('build', function() {
return gulp.src('src/**/*.js')
.pipe(babel())
.pipe(gulp.dest('dist'));
});
Use the Angular 1.4 Router
Mix Angular 1 and Angular 2 components. Mix ES5 and ES6.
ES5 Angular 1 Service
angular.module('hype', ['unicorn'])
.service('unicornHype', ['unicornHorn', '$q',
function(unicornHorn, $q) {
this.horn = unicornHorn;
this.findUnicorn = function() {
var deferred = $q.defer();
navigator.geolocation.getCurrentPosition(function(pos) {
this.horn.thrust();
deferred.resolve('The unicorn is at ' + pos.coords.latitude);
}.bind(this), deferred.reject);
return deferred.promise;
};
}
]);
It's better with ES6!
angular.module('hype', ['unicorn'])
.service('unicornHype', ['unicornHorn', '$q', UnicornHype]);
class UnicornHype {
constructor(unicornHorn, $q) {
this.$q = $q;
this.horn = unicornHorn;
}
findUnicorn() {
return this.$q((resolve, reject) => {
navigator.geolocation.getCurrentPosition((pos) => {
this.horn.thrust();
resolve(`The unicorn is at ${pos.coords.latitude}`);
}, reject);
});
}
}
Angular 2 Service
import {UnicornHorn} from "../animals/unicorn";
class UnicornHype {
constructor(unicornHorn:UnicornHorn) {
this.horn = unicornHorn;
}
findUnicorn() {
return new Promise((resolve, reject) => {
navigator.geolocation.getCurrentPosition((pos) => {
this.horn.thrust();
resolve(`The unicorn is at ${pos.coords.latitude}`);
}, reject);
});
}
}
What's the difference?
Not much.
Directives
Angular 1 directive API
The Angular 1 directive API. Simple and easy, right?
var myModule = angular.module(...);
myModule.directive('directiveName', function factory(injectables) {
var directiveDefinitionObject = {
priority: 0,
template: '<div></div>', // or // function(tElement, tAttrs) { ... },
// or
// templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },
transclude: false,
restrict: 'A',
templateNamespace: 'html',
scope: false,
controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
controllerAs: 'stringIdentifier',
require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],
compile: function compile(tElement, tAttrs, transclude) {
return {
pre: function preLink(scope, iElement, iAttrs, controller) { ... },
post: function postLink(scope, iElement, iAttrs, controller) { ... }
}
// or
// return function postLink( ... ) { ... }
},
// or
// link: {
// pre: function preLink(scope, iElement, iAttrs, controller) { ... },
// post: function postLink(scope, iElement, iAttrs, controller) { ... }
// }
// or
// link: function postLink( ... ) { ... }
};
return directiveDefinitionObject;
});
Angular 2 directives
Component Directives
<my-narwhal name="my precious narwhal"></my-narwhal>
@Component({
selector: 'my-narwhal',
bind: {
name: 'name'
}
});
@Template({
inline: '<div>He is {{ bigName() }}.</div>'
});
class Narwhal {
bigName() {
return this.name.toUpperCase();
}
}
He is MY PRECIOUS NARWHAL.
Angular 1 Directive
<my-narwhal name="my precious narwhal"></my-narwhal>
myModule.directive('myNarwhal', function () {
return {
restrict: 'E',
scope: {
name: '@'
},
link: function(scope) {
scope.bigName = function() {
return scope.name.toUpperCase();
};
},
template: '<div>He is {{ bigName() }}.</div>',
};
});
Angular 1 directives: Eliminate Scope
<my-narwhal name="my precious narwhal"></my-narwhal>
myModule.directive('myNarwhal', function () {
return {
restrict: 'E',
scope: {
name: '@',
},
controller: NarwhalController,
controllerAs: 'myNarhwal',
template: '<div>He is {{ myNarwhal.bigName() }}.</div>',
};
function NarhwalController($scope) {
this.name = scope.name;
this.bigName = function() {
return this.name.toUpperCase();
};
}
});
Angular 1 directives: eliminate scope
<my-narwhal name="my precious narwhal"></my-narwhal>
myModule.directive('myNarwhal', function() {
return {
restrict: 'E',
scope: {},
bindToController: {
name: '@',
},
controller: NarwhalController,
controllerAs: 'myNarwhal',
template: '<div>He is {{ myNarwhal.bigName() }}.</div>',
};
function NarwhalController() {
this.bigName = function() {
return this.name.toUpperCase();
};
}
});
angular.component()
<my-narwhal name="my precious narwhal"></my-narwhal>
myModule.component('myNarwhal', function () {
return {
bind: {
name: '@'
},
controller: NarwhalController,
template: '<div>He is {{ myNarwhal.bigName() }}.</div>',
};
function NarwhalController() {
this.bigName = function() {
return this.name.toUpperCase();
};
}
});
This is a proposal. See
angular/angular.js#10007
Angular 1 Component => ES6
<my-narwhal name="my precious narwhal"></my-narwhal>
myModule.component('myNarwhal', () => {
return {
bind: {
name: '@'
},
controller: Narhwal,
template: '<div>He is {{ myNarwhal.bigName() }}.</div>'
};
class Narhwal {
bigName() {
return this.name.toUpperCase();
}
}
});
Thanks!