Angular 1 | Angular 2 |
---|---|
JavaScript | TypeScript |
Orienté MV* | Orienté composant |
Double databinding | databinding presque unidrectionnel |
@Component({
selector: 'my-app',
template:`
<h1>{{title}}</h1>
<input [(ngModel)]="hero.name" placeholder="name">
`
})
export class AppComponent {
public title: string = 'Tour of Heroes';
public hero: Hero = {
id: 1,
name: 'Windstorm'
};
}
Organisation en modules techniques fonctionnels
factory
service
TurtlesService.$inject = ['$q']
function TurtlesService($q) {
var self = this;
var turtles = [{name:'Leonardo', color:'blue'}]
self.findAll = function findAll() {
return $q.resolve(turtles)
}
}
angular.module('turtles.app').service('TurtlesService', TurtlesService);
$scope
controllerAs
TurtlesCtrl.$inject = ['TurtlesService'];
function TurtlesCtrl(TurtlesService) {
var $ctrl = this;
$ctrl.turtles = [];
TurtlesService.findAll().then(function (turtles) {
$ctrl.turtles = turtles
});
}
controllerAs
angular.module('turtles.app').config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/turtles', {
templateUrl: 'src/turtles/turtles.html',
controller: 'TurtlesCtrl',
controllerAs: '$ctrl'
})
}]);
controllerAs
<ul>
<li ng-repeat="turtle in $ctrl.turtles track by turtle.name">
<span class="turtle-name">{{turtle.name}}</span>
<span class="round"
ng-style="{'background-color':turtle.color}"></span>
</li>
</ul>
component
var bootstrapInput = {
bindings: {
label: '@',
model: '<',
modelChange: '&'
},
controller: BootstrapController,
template: '<div class="form-group">' +
'<label>{{$ctrl.label}}</label>' +
'<input type="text" class="form-control" ' +
' placeholder="{{$ctrl.label}}" ' +
' ng-model="$ctrl.modelProxy" /> ' +
'</div>'
}
component
function BootstrapController() {
}
Object.defineProperty(BootstrapController.prototype, "modelProxy", {
get: function () {
return this.model;
},
set: function (newModel) {
this.modelChange({ model: newModel });
}
});
component
angular.module('my.app').component('bootstrapInput', bootstrapInput)
<bootstrap-input
label="Name"
model="myController.name"
modelChange="myController.name = model"
></bootstrap-input>
@angular/router
angular.module('app', ['ngComponentRouter', 'turtles.app'])
.component('app', {
template: '<ng-outlet></ng-outlet>',
$routeConfig: [
{
path: '/turtles/...',
name: 'Turtles',
component: 'turtles',
useAsDefault: true
}
]
})
.value('$routerRootComponent', 'app')
<app></app>
//MyMath.ts
export default function add(a, b) {
return a + b;
}
export function multiply(a, b) {
return a * b;
}
import myAdd from 'MyMath';
import {multiply} from 'MyMath';
myAdd(1, 2) //3
multiply(2, 3) //6
interface User {
firstName:string
lastName:string
}
class Room {
constructor(private users:Array<User> = []) {}
addUser(user:User) {
this.users.push(user);
}
}
const room = new Room();
room.addUser({firstName:'Georges', lastName:'Abitbol'});
Support des librairies tierces
par des fichiers d'entetes (.d.ts)
/// <reference path="main.d.ts" />
npm install systemjs jspm typings typescript
jspm install ts angular npm:@angular/router
typings install jquery angular angular-component-router --save --ambient
System.config({
//...
packages: {
"src": {
"defaultExtension": "ts",
"meta": {
"*.ts": {
"loader": "ts"
}
}
}
},
//...
});
System.import('src/app')
.then(function() {
return System.import('angular');
})
.then(function(angular) {
angular.bootstrap(document.body, ['app'], {strictDi:true});
})
.catch(function(err) {
console.log('Error: ', err, err.stack);
});
any
export interface Turtle {
name:string
color:string
}
export default class TurtlesService {
public turtles:Array<Turtle> = [{name:'Leonardo', color:'blue'}]
static $inject = ['$q'];
constructor(private $q:ng.IQService) { }
findAll():ng.IPromise<Array<Turtle>> {
return this.$q.resolve(this.turtles)
}
}
import {Turtle} from './turtleService'
import TurtlesService from './turtleService';
class TurtlesCtrl {
public turtles:Array<Turtle> = []
static $inject = ['TurtlesService'];
constructor(private TurtlesService:TurtlesService) {
TurtlesService.findAll().then(turtles => this.turtles = turtles)
}
}
$scope.$watch
class TurtlesCtrl {
public turtles:Array<Turtle> = []
get firstTurtleName():string {
return this.turtles[0] && this.turtles[0].name;
}
set firstTurtleName(firstTurtleName:string) {
if (!this.turtles[0]) {
this.turtles[0] = {name:'', color:''}
}
this.turtles[0].name = firstTurtleName;
}
}
<input ng-model="$ctrl.firstTurtleName" />
import _ from 'lodash';
export default function debounce(debounceInMs:number) {
return function (target:Object, propertyKey:string,
descriptor:TypedPropertyDescriptor<any>) {
descriptor.value = _.debounce(descriptor.value, debounceInMs);
return descriptor
}
}
class TurtlesCtrl {
@debounce(300)
search(textToSearch:string) {
//...
}
}
Ajouter du comportement transverse à des méthodes
jspm install angular2 rxjs reflect-metadata
import {UpgradeAdapter} from 'angular2/upgrade';
const upgradeAdapter = new UpgradeAdapter();
export default upgradeAdapter
System.import('src/app')
.then(function() { return System.import('reflect-metadata'); })
.then(function() { return System.import('src/upgrader'); })
.then(function(upgradeAdapter) {
upgradeAdapter.default.bootstrap(document.body, ['app']);
//angular.bootstrap(document.body, ['app'], {strictDi:true});
})
.catch(function(err) {
console.log('Error: ', err, err.stack);
});
const turtlesShow = {
bindings: {
turtles:'<'
},
template:`<ul>
<li ng-repeat="turtle in $ctrl.turtles track by turtle.name">
<span class="turtle-name">{{turtle.name}}</span>
<span class="round"
ng-style="{'background-color':turtle.color}"></span>
</li>
</ul>`
}
export default turtlesShow;
import 'reflect-metadata';
import {Component} from 'angular2/core';
import {Turtle} from './turtleService'
@Component({
selector:'turtlesShow',
template:`<ul>
<li *ngFor="#turtle of turtles">
<span class="turtle-name">{{turtle.name}}</span>
<span class="round"
[ngStyle]="{'background-color':turtle.color}"></span>
</li>
</ul>`,
inputs: ['turtles']
})
export default class TurtlesShow {
public turtles:Array<Turtle> = [];
}
import angular from 'angular';
import upgradeAdapter from 'upgrader';
angular.module('turtles.app').directive('turtlesShow',
<IDirectiveFactory>upgradeAdapter.downgradeNg2Component(turtlesShow2))
const MyAngular1Directive =
upgradeAdapter.upgradeNg1Component('myAngular1Directive');
@Component({
selector:'MyAngular2Directive',
template:`
<div>
<My-Angular1-Directive my-params="2" />
</div>`,
directives:[MyAngular1Directive]
})
export default class MyAngular2Directive {
};
#fromAngular1to2