diff --git a/public/docs/_examples/upgrade-adapter/ts/app/1-2-hybrid-bootstrap/app.module.ts b/public/docs/_examples/upgrade-adapter/ts/app/1-2-hybrid-bootstrap/app.module.ts
index b4926d8c69..6ac76407b1 100644
--- a/public/docs/_examples/upgrade-adapter/ts/app/1-2-hybrid-bootstrap/app.module.ts
+++ b/public/docs/_examples/upgrade-adapter/ts/app/1-2-hybrid-bootstrap/app.module.ts
@@ -1,18 +1,29 @@
declare var angular: any;
+// #docregion ngmodule
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+@NgModule({
+ imports: [ BrowserModule ]
+})
+export class AppModule {}
+// #enddocregion ngmodule
+angular.module('heroApp', [])
+ .controller('MainCtrl', function() {
+ this.message = 'Hello world';
+ });
+
// #docregion bootstrap
import { UpgradeAdapter } from '@angular/upgrade';
// #enddocregion bootstrap
-angular.module('heroApp', [])
- .controller('MainCtrl', function() {
- this.message = 'Hello world';
- });
+// This blank is expected to trigger the docplaster
// #docregion bootstrap
-const upgradeAdapter = new UpgradeAdapter();
+const upgradeAdapter = new UpgradeAdapter(AppModule);
upgradeAdapter.bootstrap(document.body, ['heroApp'], {strictDi: true});
// #enddocregion bootstrap
diff --git a/public/docs/_examples/upgrade-adapter/ts/app/1-2-hybrid-shared-adapter-bootstrap/upgrade_adapter.ts b/public/docs/_examples/upgrade-adapter/ts/app/1-2-hybrid-shared-adapter-bootstrap/upgrade_adapter.ts
index f6066f9109..6ccaa31b9c 100644
--- a/public/docs/_examples/upgrade-adapter/ts/app/1-2-hybrid-shared-adapter-bootstrap/upgrade_adapter.ts
+++ b/public/docs/_examples/upgrade-adapter/ts/app/1-2-hybrid-shared-adapter-bootstrap/upgrade_adapter.ts
@@ -1,3 +1,16 @@
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+@NgModule({
+ imports: [ BrowserModule ]
+})
+export class AppModule {}
+
+angular.module('heroApp', [])
+ .controller('MainCtrl', function() {
+ this.message = 'Hello world';
+ });
+
// #docregion
import { UpgradeAdapter } from '@angular/upgrade';
-export const upgradeAdapter = new UpgradeAdapter();
+export const upgradeAdapter = new UpgradeAdapter(AppModule);
diff --git a/public/docs/_examples/upgrade-adapter/ts/app/1-to-2-projection/app.module.ts b/public/docs/_examples/upgrade-adapter/ts/app/1-to-2-projection/app.module.ts
index ad48568e09..5daeb671e3 100644
--- a/public/docs/_examples/upgrade-adapter/ts/app/1-to-2-projection/app.module.ts
+++ b/public/docs/_examples/upgrade-adapter/ts/app/1-to-2-projection/app.module.ts
@@ -1,10 +1,18 @@
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
import { UpgradeAdapter } from '@angular/upgrade';
import { MainController } from './main.controller';
import { HeroDetailComponent } from './hero-detail.component';
+@NgModule({
+ imports: [ BrowserModule ],
+ declarations: [ HeroDetailComponent ]
+})
+export class AppModule {}
+
declare var angular: any;
-const upgradeAdapter = new UpgradeAdapter();
+const upgradeAdapter = new UpgradeAdapter(AppModule);
angular.module('heroApp', [])
.controller('MainController', MainController)
diff --git a/public/docs/_examples/upgrade-adapter/ts/app/1-to-2-providers/upgrade_adapter.ts b/public/docs/_examples/upgrade-adapter/ts/app/1-to-2-providers/upgrade_adapter.ts
index f6066f9109..c98ab182a8 100644
--- a/public/docs/_examples/upgrade-adapter/ts/app/1-to-2-providers/upgrade_adapter.ts
+++ b/public/docs/_examples/upgrade-adapter/ts/app/1-to-2-providers/upgrade_adapter.ts
@@ -1,3 +1,19 @@
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+import { HeroDetailComponent } from './hero-detail.component';
+
+@NgModule({
+ imports: [ BrowserModule ],
+ declarations: [ HeroDetailComponent ]
+})
+export class AppModule {}
+
+angular.module('heroApp', [])
+ .controller('MainCtrl', function() {
+ this.message = 'Hello world';
+ });
+
// #docregion
import { UpgradeAdapter } from '@angular/upgrade';
-export const upgradeAdapter = new UpgradeAdapter();
+export const upgradeAdapter = new UpgradeAdapter(AppModule);
diff --git a/public/docs/_examples/upgrade-adapter/ts/app/2-to-1-providers/app.module.ts b/public/docs/_examples/upgrade-adapter/ts/app/2-to-1-providers/app.module.ts
index 9ab3f70e94..16b77819c5 100644
--- a/public/docs/_examples/upgrade-adapter/ts/app/2-to-1-providers/app.module.ts
+++ b/public/docs/_examples/upgrade-adapter/ts/app/2-to-1-providers/app.module.ts
@@ -5,8 +5,6 @@ import { upgradeAdapter } from './upgrade_adapter';
declare var angular: any;
// #docregion register
-upgradeAdapter.addProvider(Heroes);
-
angular.module('heroApp', [])
.factory('heroes', upgradeAdapter.downgradeNg2Provider(Heroes))
.component('heroDetail', heroDetailComponent);
diff --git a/public/docs/_examples/upgrade-adapter/ts/app/2-to-1-providers/upgrade_adapter.ts b/public/docs/_examples/upgrade-adapter/ts/app/2-to-1-providers/upgrade_adapter.ts
index f6066f9109..d99d587f0f 100644
--- a/public/docs/_examples/upgrade-adapter/ts/app/2-to-1-providers/upgrade_adapter.ts
+++ b/public/docs/_examples/upgrade-adapter/ts/app/2-to-1-providers/upgrade_adapter.ts
@@ -1,3 +1,19 @@
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+// #docregion ngmodule
+import { Heroes } from './heroes';
+
+@NgModule({
+ imports: [ BrowserModule ],
+ providers: [ Heroes ]
+})
+export class AppModule {}
+// #enddocregion ngmodule
+angular.module('heroApp', [])
+ .controller('MainCtrl', function() {
+ this.message = 'Hello world';
+ });
+
// #docregion
import { UpgradeAdapter } from '@angular/upgrade';
-export const upgradeAdapter = new UpgradeAdapter();
+export const upgradeAdapter = new UpgradeAdapter(AppModule);
diff --git a/public/docs/_examples/upgrade-adapter/ts/app/2-to-1-transclusion/container.component.ts b/public/docs/_examples/upgrade-adapter/ts/app/2-to-1-transclusion/container.component.ts
index a468898e5f..1b740d6554 100644
--- a/public/docs/_examples/upgrade-adapter/ts/app/2-to-1-transclusion/container.component.ts
+++ b/public/docs/_examples/upgrade-adapter/ts/app/2-to-1-transclusion/container.component.ts
@@ -1,10 +1,7 @@
// #docregion
import { Component } from '@angular/core';
-import { upgradeAdapter } from './upgrade_adapter';
import { Hero } from '../hero';
-const HeroDetail = upgradeAdapter.upgradeNg1Component('heroDetail');
-
@Component({
selector: 'my-container',
template: `
@@ -12,8 +9,7 @@ const HeroDetail = upgradeAdapter.upgradeNg1Component('heroDetail');
{{hero.description}}
- `,
- directives: [HeroDetail]
+ `
})
export class ContainerComponent {
hero = new Hero(1, 'Windstorm', 'Specific powers of controlling winds');
diff --git a/public/docs/_examples/upgrade-adapter/ts/app/2-to-1-transclusion/upgrade_adapter.ts b/public/docs/_examples/upgrade-adapter/ts/app/2-to-1-transclusion/upgrade_adapter.ts
index f6066f9109..b0f947c8e5 100644
--- a/public/docs/_examples/upgrade-adapter/ts/app/2-to-1-transclusion/upgrade_adapter.ts
+++ b/public/docs/_examples/upgrade-adapter/ts/app/2-to-1-transclusion/upgrade_adapter.ts
@@ -1,3 +1,20 @@
// #docregion
import { UpgradeAdapter } from '@angular/upgrade';
-export const upgradeAdapter = new UpgradeAdapter();
+import { NgModule, forwardRef } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+import { ContainerComponent } from './container.component';
+
+export const upgradeAdapter = new UpgradeAdapter(forwardRef(() => AppModule));
+const HeroDetail = upgradeAdapter.upgradeNg1Component('heroDetail');
+
+@NgModule({
+ imports: [ BrowserModule ],
+ declarations: [ ContainerComponent, HeroDetail ]
+})
+export class AppModule {}
+
+angular.module('heroApp', [])
+ .controller('MainCtrl', function() {
+ this.message = 'Hello world';
+ });
diff --git a/public/docs/_examples/upgrade-adapter/ts/app/downgrade-io/app.module.ts b/public/docs/_examples/upgrade-adapter/ts/app/downgrade-io/app.module.ts
index d9af4e0104..a09db040d1 100644
--- a/public/docs/_examples/upgrade-adapter/ts/app/downgrade-io/app.module.ts
+++ b/public/docs/_examples/upgrade-adapter/ts/app/downgrade-io/app.module.ts
@@ -1,11 +1,21 @@
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
import { MainController } from './main.controller';
// #docregion downgradecomponent
import { HeroDetailComponent } from './hero-detail.component';
// #enddocregion downgradecomponent
+
+@NgModule({
+ imports: [ BrowserModule ],
+ declarations: [ HeroDetailComponent ]
+})
+export class AppModule {}
+
import { UpgradeAdapter } from '@angular/upgrade';
-const upgradeAdapter = new UpgradeAdapter();
+const upgradeAdapter = new UpgradeAdapter(AppModule);
// #docregion downgradecomponent
diff --git a/public/docs/_examples/upgrade-adapter/ts/app/downgrade-static/app.module.ts b/public/docs/_examples/upgrade-adapter/ts/app/downgrade-static/app.module.ts
index 44935340f0..d5f173b5b5 100644
--- a/public/docs/_examples/upgrade-adapter/ts/app/downgrade-static/app.module.ts
+++ b/public/docs/_examples/upgrade-adapter/ts/app/downgrade-static/app.module.ts
@@ -1,10 +1,19 @@
-// #docregion downgradecomponent
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+// #docregion downgradecomponent, ngmodule
import { HeroDetailComponent } from './hero-detail.component';
// #enddocregion downgradecomponent
+@NgModule({
+ imports: [ BrowserModule ],
+ declarations: [ HeroDetailComponent ]
+})
+export class AppModule {}
+// #enddocregion ngmodule
import { UpgradeAdapter } from '@angular/upgrade';
-const upgradeAdapter = new UpgradeAdapter();
+const upgradeAdapter = new UpgradeAdapter(AppModule);
// #docregion downgradecomponent
diff --git a/public/docs/_examples/upgrade-adapter/ts/app/upgrade-io/container.component.ts b/public/docs/_examples/upgrade-adapter/ts/app/upgrade-io/container.component.ts
index 0055370ea8..8d76085174 100644
--- a/public/docs/_examples/upgrade-adapter/ts/app/upgrade-io/container.component.ts
+++ b/public/docs/_examples/upgrade-adapter/ts/app/upgrade-io/container.component.ts
@@ -1,10 +1,7 @@
// #docregion
import { Component } from '@angular/core';
-import { upgradeAdapter } from './upgrade_adapter';
import { Hero } from '../hero';
-const HeroDetail = upgradeAdapter.upgradeNg1Component('heroDetail');
-
@Component({
selector: 'my-container',
template: `
@@ -12,8 +9,7 @@ const HeroDetail = upgradeAdapter.upgradeNg1Component('heroDetail');
- `,
- directives: [HeroDetail]
+ `
})
export class ContainerComponent {
hero = new Hero(1, 'Windstorm');
diff --git a/public/docs/_examples/upgrade-adapter/ts/app/upgrade-io/upgrade_adapter.ts b/public/docs/_examples/upgrade-adapter/ts/app/upgrade-io/upgrade_adapter.ts
index f6066f9109..b0f947c8e5 100644
--- a/public/docs/_examples/upgrade-adapter/ts/app/upgrade-io/upgrade_adapter.ts
+++ b/public/docs/_examples/upgrade-adapter/ts/app/upgrade-io/upgrade_adapter.ts
@@ -1,3 +1,20 @@
// #docregion
import { UpgradeAdapter } from '@angular/upgrade';
-export const upgradeAdapter = new UpgradeAdapter();
+import { NgModule, forwardRef } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+import { ContainerComponent } from './container.component';
+
+export const upgradeAdapter = new UpgradeAdapter(forwardRef(() => AppModule));
+const HeroDetail = upgradeAdapter.upgradeNg1Component('heroDetail');
+
+@NgModule({
+ imports: [ BrowserModule ],
+ declarations: [ ContainerComponent, HeroDetail ]
+})
+export class AppModule {}
+
+angular.module('heroApp', [])
+ .controller('MainCtrl', function() {
+ this.message = 'Hello world';
+ });
diff --git a/public/docs/_examples/upgrade-adapter/ts/app/upgrade-static/container.component.ts b/public/docs/_examples/upgrade-adapter/ts/app/upgrade-static/container.component.ts
index ca8a93dd26..1e3ebf509b 100644
--- a/public/docs/_examples/upgrade-adapter/ts/app/upgrade-static/container.component.ts
+++ b/public/docs/_examples/upgrade-adapter/ts/app/upgrade-static/container.component.ts
@@ -1,16 +1,12 @@
// #docregion
import { Component } from '@angular/core';
-import { upgradeAdapter } from './upgrade_adapter';
-
-const HeroDetail = upgradeAdapter.upgradeNg1Component('heroDetail');
@Component({
selector: 'my-container',
template: `
Tour of Heroes
- `,
- directives: [HeroDetail]
+ `
})
export class ContainerComponent {
diff --git a/public/docs/_examples/upgrade-adapter/ts/app/upgrade-static/upgrade_adapter.ts b/public/docs/_examples/upgrade-adapter/ts/app/upgrade-static/upgrade_adapter.ts
index f6066f9109..c9173347bc 100644
--- a/public/docs/_examples/upgrade-adapter/ts/app/upgrade-static/upgrade_adapter.ts
+++ b/public/docs/_examples/upgrade-adapter/ts/app/upgrade-static/upgrade_adapter.ts
@@ -1,3 +1,23 @@
// #docregion
import { UpgradeAdapter } from '@angular/upgrade';
-export const upgradeAdapter = new UpgradeAdapter();
+import { NgModule, forwardRef } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+import { ContainerComponent } from './container.component';
+
+export const upgradeAdapter = new UpgradeAdapter(forwardRef(() => AppModule));
+
+// #docregion heroupgrade
+const HeroDetail = upgradeAdapter.upgradeNg1Component('heroDetail');
+
+@NgModule({
+ imports: [ BrowserModule ],
+ declarations: [ ContainerComponent, HeroDetail ]
+})
+export class AppModule {}
+// #enddocregion heroupgrade
+
+angular.module('heroApp', [])
+ .controller('MainCtrl', function() {
+ this.message = 'Hello world';
+ });
diff --git a/public/docs/_examples/upgrade-adapter/ts/index-1-2-hybrid-bootstrap.html b/public/docs/_examples/upgrade-adapter/ts/index-1-2-hybrid-bootstrap.html
index ff5481a40d..fc090c9eb9 100644
--- a/public/docs/_examples/upgrade-adapter/ts/index-1-2-hybrid-bootstrap.html
+++ b/public/docs/_examples/upgrade-adapter/ts/index-1-2-hybrid-bootstrap.html
@@ -16,9 +16,6 @@
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/karma-test-shim.1.js b/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/karma-test-shim.1.js
index 31589119d2..19fcc89fe9 100644
--- a/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/karma-test-shim.1.js
+++ b/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/karma-test-shim.1.js
@@ -1,21 +1,25 @@
// #docregion
// /*global jasmine, __karma__, window*/
-Error.stackTraceLimit = Infinity;
+Error.stackTraceLimit = 0; // "No stacktrace"" is usually best for app testing.
+
+// Uncomment to get full stacktrace output. Sometimes helpful, usually not.
+// Error.stackTraceLimit = Infinity; //
+
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000;
-__karma__.loaded = function () {
-};
+var builtPath = '/base/app/';
+
+__karma__.loaded = function () { };
function isJsFile(path) {
return path.slice(-3) == '.js';
}
function isSpecFile(path) {
- return /\.spec\.js$/.test(path);
+ return /\.spec\.(.*\.)?js$/.test(path);
}
function isBuiltFile(path) {
- var builtPath = '/base/app/';
return isJsFile(path) && (path.substr(0, builtPath.length) == builtPath);
}
@@ -25,27 +29,61 @@ var allSpecFiles = Object.keys(window.__karma__.files)
System.config({
baseURL: '/base',
- packageWithIndex: true // sadly, we can't use umd packages (yet?)
+ // Extend usual application package list with test folder
+ packages: { 'testing': { main: 'index.js', defaultExtension: 'js' } },
+
+ // Assume npm: is set in `paths` in systemjs.config
+ // Map the angular testing umd bundles
+ map: {
+ '@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js',
+ '@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js',
+ '@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js',
+ '@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
+ '@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',
+ '@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js',
+ '@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js',
+ '@angular/forms/testing': 'npm:@angular/forms/bundles/forms-testing.umd.js',
+ },
});
System.import('systemjs.config.js')
- .then(() => Promise.all([
- System.import('@angular/core/testing'),
- System.import('@angular/platform-browser-dynamic/testing')
- ]))
- .then((providers) => {
- var coreTesting = providers[0];
+ .then(importSystemJsExtras)
+ .then(initTestBed)
+ .then(initTesting);
+
+/** Optional SystemJS configuration extras. Keep going w/o it */
+function importSystemJsExtras(){
+ return System.import('systemjs.config.extras.js')
+ .catch(function(reason) {
+ console.log(
+ 'Warning: System.import could not load the optional "systemjs.config.extras.js". Did you omit it by accident? Continuing without it.'
+ );
+ console.log(reason);
+ });
+}
+
+function initTestBed(){
+ return Promise.all([
+ System.import('@angular/core/testing'),
+ System.import('@angular/platform-browser-dynamic/testing')
+ ])
+
+ .then(function (providers) {
+ var coreTesting = providers[0];
var browserTesting = providers[1];
+
coreTesting.TestBed.initTestEnvironment(
browserTesting.BrowserDynamicTestingModule,
browserTesting.platformBrowserDynamicTesting());
})
- .then(function () {
- // Finally, load all spec files.
- // This will run the tests directly.
- return Promise.all(
- allSpecFiles.map(function (moduleName) {
- return System.import(moduleName);
- }));
- })
+}
+
+// Import all spec files and start karma
+function initTesting () {
+ return Promise.all(
+ allSpecFiles.map(function (moduleName) {
+ return System.import(moduleName);
+ })
+ )
.then(__karma__.start, __karma__.error);
+}
diff --git a/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/karma.conf.ng1.js b/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/karma.conf.ng1.js
index 48cc490f89..3decfbdd3e 100644
--- a/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/karma.conf.ng1.js
+++ b/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/karma.conf.ng1.js
@@ -63,11 +63,10 @@ module.exports = function(config) {
frameworks: ['jasmine'],
- browsers: ['Chrome', 'Firefox'],
+ browsers: ['Chrome'],
plugins: [
'karma-chrome-launcher',
- 'karma-firefox-launcher',
'karma-jasmine'
]
diff --git a/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/systemjs.config.1.js b/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/systemjs.config.1.js
index a54f8bb20c..18b947dbb5 100644
--- a/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/systemjs.config.1.js
+++ b/public/docs/_examples/upgrade-phonecat-2-hybrid/ts/systemjs.config.1.js
@@ -1,59 +1,47 @@
/**
- * System configuration for Angular 2 samples
+ * System configuration for Angular samples
* Adjust as necessary for your application needs.
*/
-(function(global) {
-
- // map tells the System loader where to look for things
+(function (global) {
// #docregion paths
- var map = {
- 'app': '/app', // 'dist',
-
- '@angular': '/node_modules/@angular',
- 'angular-in-memory-web-api': '/node_modules/angular-in-memory-web-api',
- 'rxjs': '/node_modules/rxjs'
- };
-
- var packages = {
- '/app': { main: 'main.js', defaultExtension: 'js' },
- 'rxjs': { defaultExtension: 'js' },
- 'angular-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' },
- };
- // #enddocregion paths
-
- var ngPackageNames = [
- 'common',
- 'compiler',
- 'core',
- 'forms',
- 'http',
- 'platform-browser',
- 'platform-browser-dynamic',
- 'router',
- 'router-deprecated',
- 'upgrade',
- ];
-
- // Individual files (~300 requests):
- function packIndex(pkgName) {
- packages['@angular/'+pkgName] = { main: 'index.js', defaultExtension: 'js' };
- }
-
- // Bundled (~40 requests):
- function packUmd(pkgName) {
- packages['@angular/'+pkgName] = { main: '/bundles/' + pkgName + '.umd.js', defaultExtension: 'js' };
- }
-
- var setPackageConfig = System.packageWithIndex ? packIndex : packUmd;
-
- // Add package entries for angular packages
- ngPackageNames.forEach(setPackageConfig);
-
- var config = {
- map: map,
- packages: packages
- }
-
- System.config(config);
+ System.config({
+ paths: {
+ // paths serve as alias
+ 'npm:': '/node_modules/'
+ },
+ map: {
+ app: '/app',
+ // #enddocregion paths
+ // angular bundles
+ '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
+ '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
+ '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
+ '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
+ '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
+ '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
+ '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
+ '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
+ '@angular/upgrade': 'npm:@angular/upgrade/bundles/upgrade.umd.js',
+ // other libraries
+ 'rxjs': 'npm:rxjs',
+ 'angular-in-memory-web-api': 'npm:angular-in-memory-web-api',
+ // #docregion paths
+ },
+ // #enddocregion paths
+ // packages tells the System loader how to load when no filename and/or no extension
+ packages: {
+ 'app': {
+ main: './main.js',
+ defaultExtension: 'js'
+ },
+ rxjs: {
+ defaultExtension: 'js'
+ },
+ 'angular-in-memory-web-api': {
+ main: './index.js',
+ defaultExtension: 'js'
+ }
+ }
+ });
})(this);
diff --git a/public/docs/_examples/upgrade-phonecat-3-final/e2e-spec.ts.disabled b/public/docs/_examples/upgrade-phonecat-3-final/e2e-spec.ts
similarity index 100%
rename from public/docs/_examples/upgrade-phonecat-3-final/e2e-spec.ts.disabled
rename to public/docs/_examples/upgrade-phonecat-3-final/e2e-spec.ts
diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/app-routing.module.ts b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/app-routing.module.ts
new file mode 100644
index 0000000000..16a72b069e
--- /dev/null
+++ b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/app-routing.module.ts
@@ -0,0 +1,23 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { Routes, RouterModule } from '@angular/router';
+import { APP_BASE_HREF, HashLocationStrategy, LocationStrategy } from '@angular/common';
+
+import { PhoneDetailComponent } from './phone-detail/phone-detail.component';
+import { PhoneListComponent } from './phone-list/phone-list.component';
+
+const routes: Routes = [
+ { path: '', redirectTo: 'phones', pathMatch: 'full' },
+ { path: 'phones', component: PhoneListComponent },
+ { path: 'phones/:phoneId', component: PhoneDetailComponent }
+];
+
+@NgModule({
+ imports: [ RouterModule.forRoot(routes) ],
+ exports: [ RouterModule ],
+ providers: [
+ { provide: APP_BASE_HREF, useValue: '!' },
+ { provide: LocationStrategy, useClass: HashLocationStrategy },
+ ]
+})
+export class AppRoutingModule {}
diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/app.component.ts b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/app.component.ts
index af4e91c80f..fa4e5f7f4b 100644
--- a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/app.component.ts
+++ b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/app.component.ts
@@ -1,18 +1,9 @@
// #docregion
import { Component } from '@angular/core';
-import { RouteConfig, ROUTER_DIRECTIVES } from '@angular/router-deprecated';
-import { PhoneListComponent } from './phone-list/phone-list.component';
-import { PhoneDetailComponent } from './phone-detail/phone-detail.component';
-@RouteConfig([
- {path: '/phones', name: 'Phones', component: PhoneListComponent},
- {path: '/phones/:phoneId', name: 'Phone', component: PhoneDetailComponent},
- {path: '/', redirectTo: ['Phones']}
-])
@Component({
selector: 'phonecat-app',
- template: '',
- directives: [ROUTER_DIRECTIVES]
+ template: ''
})
export class AppComponent {
}
diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/app.module.ts b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/app.module.ts
new file mode 100644
index 0000000000..58acb5bce3
--- /dev/null
+++ b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/app.module.ts
@@ -0,0 +1,34 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { FormsModule } from '@angular/forms';
+import { HttpModule } from '@angular/http';
+
+import { AppRoutingModule } from './app-routing.module';
+import { AppComponent } from './app.component';
+import { CheckmarkPipe } from './core/checkmark/checkmark.pipe';
+import { Phone } from './core/phone/phone.service';
+import { PhoneDetailComponent } from './phone-detail/phone-detail.component';
+import { PhoneListComponent } from './phone-list/phone-list.component';
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ FormsModule,
+ HttpModule,
+ AppRoutingModule
+ ],
+ declarations: [
+ AppComponent,
+ PhoneListComponent,
+ CheckmarkPipe,
+ PhoneDetailComponent
+ ],
+ providers: [
+ Phone,
+ ],
+ // #docregion bootstrap
+ bootstrap: [ AppComponent ]
+ // #enddocregion bootstrap
+})
+export class AppModule {}
diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/core/checkmark/checkmark.pipe.spec.ts b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/core/checkmark/checkmark.pipe.spec.ts
index b3a1c59a8d..75150500a6 100644
--- a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/core/checkmark/checkmark.pipe.spec.ts
+++ b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/core/checkmark/checkmark.pipe.spec.ts
@@ -1,21 +1,10 @@
-import {
- describe,
- beforeEachProviders,
- it,
- inject,
- expect
-} from '@angular/core/testing';
import { CheckmarkPipe } from './checkmark.pipe';
describe('CheckmarkPipe', function() {
- beforeEachProviders(() => [CheckmarkPipe]);
-
- it('should convert boolean values to unicode checkmark or cross',
- inject([CheckmarkPipe], function(checkmarkPipe: CheckmarkPipe) {
- expect(checkmarkPipe.transform(true)).toBe('\u2713');
- expect(checkmarkPipe.transform(false)).toBe('\u2718');
- })
- );
-
+ it('should convert boolean values to unicode checkmark or cross', function () {
+ const checkmarkPipe = new CheckmarkPipe();
+ expect(checkmarkPipe.transform(true)).toBe('\u2713');
+ expect(checkmarkPipe.transform(false)).toBe('\u2718');
+ });
});
diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/core/phone/phone.service.spec.ts b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/core/phone/phone.service.spec.ts
index c9f511913b..e3a422965b 100644
--- a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/core/phone/phone.service.spec.ts
+++ b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/core/phone/phone.service.spec.ts
@@ -1,10 +1,4 @@
-import {
- describe,
- beforeEach,
- beforeEachProviders,
- it,
- inject
-} from '@angular/core/testing';
+import { inject, TestBed } from '@angular/core/testing';
import {
Http,
BaseRequestOptions,
@@ -23,15 +17,19 @@ describe('Phone', function() {
];
let mockBackend: MockBackend;
- beforeEachProviders(() => [
- Phone,
- MockBackend,
- BaseRequestOptions,
- { provide: Http,
- useFactory: (backend: MockBackend, options: BaseRequestOptions) => new Http(backend, options),
- deps: [MockBackend, BaseRequestOptions]
- }
- ]);
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ providers: [
+ Phone,
+ MockBackend,
+ BaseRequestOptions,
+ { provide: Http,
+ useFactory: (backend: MockBackend, options: BaseRequestOptions) => new Http(backend, options),
+ deps: [MockBackend, BaseRequestOptions]
+ }
+ ]
+ });
+ });
beforeEach(inject([MockBackend, Phone], (_mockBackend_: MockBackend, _phone_: Phone) => {
mockBackend = _mockBackend_;
diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/dell-venue.0.jpg b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/dell-venue.0.jpg
new file mode 100644
index 0000000000..b4cb4eb25f
Binary files /dev/null and b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/dell-venue.0.jpg differ
diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/droid-2-global-by-motorola.0.jpg b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/droid-2-global-by-motorola.0.jpg
new file mode 100644
index 0000000000..60700a2ab3
Binary files /dev/null and b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/droid-2-global-by-motorola.0.jpg differ
diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/droid-pro-by-motorola.0.jpg b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/droid-pro-by-motorola.0.jpg
new file mode 100644
index 0000000000..c7710de986
Binary files /dev/null and b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/droid-pro-by-motorola.0.jpg differ
diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/lg-axis.0.jpg b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/lg-axis.0.jpg
new file mode 100644
index 0000000000..55e5a23bb2
Binary files /dev/null and b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/lg-axis.0.jpg differ
diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/motorola-bravo-with-motoblur.0.jpg b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/motorola-bravo-with-motoblur.0.jpg
new file mode 100644
index 0000000000..e452ae7e7c
Binary files /dev/null and b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/motorola-bravo-with-motoblur.0.jpg differ
diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/motorola-charm-with-motoblur.0.jpg b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/motorola-charm-with-motoblur.0.jpg
new file mode 100644
index 0000000000..21e4b8d741
Binary files /dev/null and b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/motorola-charm-with-motoblur.0.jpg differ
diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/motorola-defy-with-motoblur.0.jpg b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/motorola-defy-with-motoblur.0.jpg
new file mode 100644
index 0000000000..c7c5e3ba0c
Binary files /dev/null and b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/motorola-defy-with-motoblur.0.jpg differ
diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/samsung-galaxy-tab.0.jpg b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/samsung-galaxy-tab.0.jpg
new file mode 100644
index 0000000000..3750377ad9
Binary files /dev/null and b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/samsung-galaxy-tab.0.jpg differ
diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/samsung-gem.0.jpg b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/samsung-gem.0.jpg
new file mode 100644
index 0000000000..0d5024a026
Binary files /dev/null and b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/samsung-gem.0.jpg differ
diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/samsung-mesmerize-a-galaxy-s-phone.0.jpg b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/samsung-mesmerize-a-galaxy-s-phone.0.jpg
new file mode 100644
index 0000000000..11b8f860cb
Binary files /dev/null and b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/samsung-mesmerize-a-galaxy-s-phone.0.jpg differ
diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/samsung-showcase-a-galaxy-s-phone.0.jpg b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/samsung-showcase-a-galaxy-s-phone.0.jpg
new file mode 100644
index 0000000000..11b8f860cb
Binary files /dev/null and b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/samsung-showcase-a-galaxy-s-phone.0.jpg differ
diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/samsung-transform.0.jpg b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/samsung-transform.0.jpg
new file mode 100644
index 0000000000..0e3107caf5
Binary files /dev/null and b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/samsung-transform.0.jpg differ
diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/sanyo-zio.0.jpg b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/sanyo-zio.0.jpg
new file mode 100644
index 0000000000..9eeb9b96ed
Binary files /dev/null and b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/sanyo-zio.0.jpg differ
diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/t-mobile-g2.0.jpg b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/t-mobile-g2.0.jpg
new file mode 100644
index 0000000000..6b6c09e058
Binary files /dev/null and b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/t-mobile-g2.0.jpg differ
diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/t-mobile-mytouch-4g.0.jpg b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/t-mobile-mytouch-4g.0.jpg
new file mode 100644
index 0000000000..beba1f6827
Binary files /dev/null and b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/img/phones/t-mobile-mytouch-4g.0.jpg differ
diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/main.ts b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/main.ts
index 4db648092b..08be7a99ba 100644
--- a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/main.ts
+++ b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/main.ts
@@ -1,27 +1,10 @@
// #docregion
// #docregion imports
-import {
- LocationStrategy,
- HashLocationStrategy,
- APP_BASE_HREF
-} from '@angular/common';
-import { bootstrap } from '@angular/platform-browser-dynamic';
-import { FormsModule } from '@angular/forms';
-import { HTTP_PROVIDERS } from '@angular/http';
-import { ROUTER_PROVIDERS } from '@angular/router-deprecated';
-import { Phone } from './core/phone/phone.service';
-import { AppComponent } from './app.component';
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+
+import { AppModule } from './app.module';
// #enddocregion imports
// #docregion bootstrap
-bootstrap(AppComponent, {
- imports: [FormsModule],
- providers: [
- HTTP_PROVIDERS,
- ROUTER_PROVIDERS,
- { provide: APP_BASE_HREF, useValue: '!' },
- { provide: LocationStrategy, useClass: HashLocationStrategy },
- Phone
- ]
-});
+platformBrowserDynamic().bootstrapModule(AppModule);
// #enddocregion bootstrap
diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/phone-detail/phone-detail.component.spec.ts b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/phone-detail/phone-detail.component.spec.ts
index 79b3cddcfb..e3b9143a94 100644
--- a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/phone-detail/phone-detail.component.spec.ts
+++ b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/phone-detail/phone-detail.component.spec.ts
@@ -1,25 +1,15 @@
// #docregion
-import { HTTP_PROVIDERS } from '@angular/http';
-// #docregion routeparams
-import { RouteParams } from '@angular/router-deprecated';
+// #docregion activatedroute
+import { ActivatedRoute } from '@angular/router';
-// #enddocregion routeparams
+// #enddocregion activatedroute
import { Observable } from 'rxjs/Rx';
-import {
- describe,
- beforeEachProviders,
- inject,
- it,
- expect
-} from '@angular/core/testing';
-import {
- TestComponentBuilder,
- ComponentFixture
-} from '@angular/compiler/testing';
+import { async, TestBed } from '@angular/core/testing';
import { PhoneDetailComponent } from './phone-detail.component';
import { Phone, PhoneData } from '../core/phone/phone.service';
+import { CheckmarkPipe } from '../core/checkmark/checkmark.pipe';
function xyzPhoneData(): PhoneData {
return {
@@ -29,31 +19,41 @@ function xyzPhoneData(): PhoneData {
};
}
-class MockPhone extends Phone {
+class MockPhone {
get(id: string): Observable {
return Observable.of(xyzPhoneData());
}
}
+// #docregion activatedroute
+
+class ActivatedRouteMock {
+ constructor(public snapshot: any) {}
+}
+
+// #enddocregion activatedroute
+
describe('PhoneDetailComponent', () => {
- // #docregion routeparams
+ // #docregion activatedroute
- beforeEachProviders(() => [
- { provide: Phone, useClass: MockPhone },
- { provide: RouteParams, useValue: new RouteParams({phoneId: 'xyz'})},
- HTTP_PROVIDERS
- ]);
- // #enddocregion routeparams
-
- it('should fetch phone detail',
- inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
- return tcb.createAsync(PhoneDetailComponent)
- .then((fixture: ComponentFixture) => {
- fixture.detectChanges();
- let compiled = fixture.debugElement.nativeElement;
- expect(compiled.querySelector('h1')).toHaveText(xyzPhoneData().name);
- });
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ CheckmarkPipe, PhoneDetailComponent ],
+ providers: [
+ { provide: Phone, useClass: MockPhone },
+ { provide: ActivatedRoute, useValue: new ActivatedRouteMock({ params: { 'phoneId': 1 } }) }
+ ]
+ })
+ .compileComponents();
}));
+ // #enddocregion activatedroute
+
+ it('should fetch phone detail', () => {
+ const fixture = TestBed.createComponent(PhoneDetailComponent);
+ fixture.detectChanges();
+ let compiled = fixture.debugElement.nativeElement;
+ expect(compiled.querySelector('h1').textContent).toContain(xyzPhoneData().name);
+ });
});
diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/phone-detail/phone-detail.component.ts b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/phone-detail/phone-detail.component.ts
index 7d42e20dee..ceba9a6f70 100644
--- a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/phone-detail/phone-detail.component.ts
+++ b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/phone-detail/phone-detail.component.ts
@@ -1,25 +1,25 @@
// #docplaster
// #docregion
-import { Component } from '@angular/core';
-import { RouteParams } from '@angular/router-deprecated';
+import { Component } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+
import { Phone, PhoneData } from '../core/phone/phone.service';
-import { CheckmarkPipe } from '../core/checkmark/checkmark.pipe';
@Component({
moduleId: module.id,
selector: 'phone-detail',
- templateUrl: 'phone-detail.template.html',
- pipes: [ CheckmarkPipe ]
+ templateUrl: 'phone-detail.template.html'
})
export class PhoneDetailComponent {
phone: PhoneData;
mainImageUrl: string;
- constructor(routeParams: RouteParams, phone: Phone) {
- phone.get(routeParams.get('phoneId')).subscribe(phone => {
- this.phone = phone;
- this.setImage(phone.images[0]);
- });
+ constructor(activatedRoute: ActivatedRoute, phone: Phone) {
+ phone.get(activatedRoute.snapshot.params['phoneId'])
+ .subscribe((p: PhoneData) => {
+ this.phone = p;
+ this.setImage(p.images[0]);
+ });
}
setImage(imageUrl: string) {
diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/phone-list/phone-list.component.spec.ts b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/phone-list/phone-list.component.spec.ts
index 3d6cd93b15..834c93df8f 100644
--- a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/phone-list/phone-list.component.spec.ts
+++ b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/phone-list/phone-list.component.spec.ts
@@ -1,42 +1,21 @@
/* tslint:disable */
// #docregion routestuff
-import { Directive } from '@angular/core';
-import { HTTP_PROVIDERS } from '@angular/http';
-import {
- Router,
- RouterLink,
- RootRouter,
- RouteRegistry,
- ROUTER_PRIMARY_COMPONENT
-} from '@angular/router-deprecated';
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
import { Observable } from 'rxjs/Rx';
-import {
- describe,
- addProviders,
- inject,
- it,
- expect,
- // MockApplicationRef
-} from '@angular/core/testing';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { SpyLocation } from '@angular/common/testing';
-import {
- TestComponentBuilder,
- ComponentFixture
-} from '@angular/core/testing';
-import { AppComponent } from '../app.component';
import { PhoneListComponent } from './phone-list.component';
import { Phone, PhoneData } from '../core/phone/phone.service';
// #enddocregion routestuff
-@Directive({
- selector: '[routerLink]',
- inputs: ['routeParams: routerLink', 'target: target']
-})
-class RouterLinkMock {}
+class ActivatedRouteMock {
+ constructor(public snapshot: any) {}
+}
-class MockPhone extends Phone {
+class MockPhone {
query(): Observable {
return Observable.of([
{name: 'Nexus S', snippet: '', images: []},
@@ -45,52 +24,48 @@ class MockPhone extends Phone {
}
}
+let fixture: ComponentFixture;
+
describe('PhoneList', () => {
// #docregion routestuff
- addProviders([
- RouteRegistry,
- { provide: Router, useClass: RootRouter },
- { provide: ROUTER_PRIMARY_COMPONENT, useValue: AppComponent },
- { provide: Location, useClass: SpyLocation},
- { provide: Phone, useClass: MockPhone},
- HTTP_PROVIDERS
- ]);
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ PhoneListComponent ],
+ providers: [
+ { provide: ActivatedRoute, useValue: new ActivatedRouteMock({ params: { 'phoneId': 1 } }) },
+ { provide: Location, useClass: SpyLocation },
+ { provide: Phone, useClass: MockPhone },
+ ],
+ schemas: [ NO_ERRORS_SCHEMA ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(PhoneListComponent);
+ });
// #enddocregion routestuff
- it('should create "phones" model with 2 phones fetched from xhr',
- inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
- return tcb
- .overrideDirective(AppComponent, RouterLink, RouterLinkMock)
- .overrideDirective(PhoneListComponent, RouterLink, RouterLinkMock)
- .createAsync(PhoneListComponent)
- .then((fixture: ComponentFixture) => {
- fixture.detectChanges();
- let compiled = fixture.debugElement.nativeElement;
- expect(compiled.querySelectorAll('.phone-list-item').length).toBe(2);
- expect(
- compiled.querySelector('.phone-list-item:nth-child(1)').textContent
- ).toContain('Motorola DROID');
- expect(
- compiled.querySelector('.phone-list-item:nth-child(2)').textContent
- ).toContain('Nexus S');
- });
- }));
+ it('should create "phones" model with 2 phones fetched from xhr', () => {
+ fixture.detectChanges();
+ let compiled = fixture.debugElement.nativeElement;
+ expect(compiled.querySelectorAll('.phone-list-item').length).toBe(2);
+ expect(
+ compiled.querySelector('.phone-list-item:nth-child(1)').textContent
+ ).toContain('Motorola DROID');
+ expect(
+ compiled.querySelector('.phone-list-item:nth-child(2)').textContent
+ ).toContain('Nexus S');
+ });
- it('should set the default value of orderProp model',
- inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
- return tcb
- .overrideDirective(AppComponent, RouterLink, RouterLinkMock)
- .overrideDirective(PhoneListComponent, RouterLink, RouterLinkMock)
- .createAsync(PhoneListComponent)
- .then((fixture: ComponentFixture) => {
- fixture.detectChanges();
- let compiled = fixture.debugElement.nativeElement;
- expect(
- compiled.querySelector('select option:last-child').selected
- ).toBe(true);
- });
- }));
+ xit('should set the default value of orderProp model', () => {
+ fixture.detectChanges();
+ let compiled = fixture.debugElement.nativeElement;
+ expect(
+ compiled.querySelector('select option:last-child').selected
+ ).toBe(true);
+ });
});
diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/phone-list/phone-list.component.ts b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/phone-list/phone-list.component.ts
index e97e740415..abbe27c5f2 100644
--- a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/phone-list/phone-list.component.ts
+++ b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/phone-list/phone-list.component.ts
@@ -1,14 +1,13 @@
// #docplaster
// #docregion top
import { Component } from '@angular/core';
-import { RouterLink } from '@angular/router-deprecated';
+
import { Phone, PhoneData } from '../core/phone/phone.service';
@Component({
moduleId: module.id,
selector: 'phone-list',
templateUrl: 'phone-list.template.html',
- directives: [ RouterLink ]
})
// #enddocregion top
export class PhoneListComponent {
@@ -41,20 +40,20 @@ export class PhoneListComponent {
}
private sortPhones(phones: PhoneData[]) {
- if (phones && this.orderProp) {
- return phones
- .slice(0) // Make a copy
- .sort((a, b) => {
- if (a[this.orderProp] < b[this.orderProp]) {
- return -1;
- } else if ([b[this.orderProp] < a[this.orderProp]]) {
- return 1;
- } else {
- return 0;
- }
- });
- }
- return phones;
+ if (phones && this.orderProp) {
+ return phones
+ .slice(0) // Make a copy
+ .sort((a, b) => {
+ if (a[this.orderProp] < b[this.orderProp]) {
+ return -1;
+ } else if ([b[this.orderProp] < a[this.orderProp]]) {
+ return 1;
+ } else {
+ return 0;
+ }
+ });
+ }
+ return phones;
}
// #enddocregion getphones
// #docregion initialclass
diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/phone-list/phone-list.template.html b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/phone-list/phone-list.template.html
index 9846664768..b4a994b297 100644
--- a/public/docs/_examples/upgrade-phonecat-3-final/ts/app/phone-list/phone-list.template.html
+++ b/public/docs/_examples/upgrade-phonecat-3-final/ts/app/phone-list/phone-list.template.html
@@ -26,10 +26,10 @@
diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/karma.conf.ng1.js b/public/docs/_examples/upgrade-phonecat-3-final/ts/karma.conf.ng1.js
index 48cc490f89..3decfbdd3e 100644
--- a/public/docs/_examples/upgrade-phonecat-3-final/ts/karma.conf.ng1.js
+++ b/public/docs/_examples/upgrade-phonecat-3-final/ts/karma.conf.ng1.js
@@ -63,11 +63,10 @@ module.exports = function(config) {
frameworks: ['jasmine'],
- browsers: ['Chrome', 'Firefox'],
+ browsers: ['Chrome'],
plugins: [
'karma-chrome-launcher',
- 'karma-firefox-launcher',
'karma-jasmine'
]
diff --git a/public/docs/_examples/upgrade-phonecat-3-final/ts/systemjs.config.1.js b/public/docs/_examples/upgrade-phonecat-3-final/ts/systemjs.config.1.js
index a54f8bb20c..592029cd65 100644
--- a/public/docs/_examples/upgrade-phonecat-3-final/ts/systemjs.config.1.js
+++ b/public/docs/_examples/upgrade-phonecat-3-final/ts/systemjs.config.1.js
@@ -1,59 +1,47 @@
/**
- * System configuration for Angular 2 samples
+ * System configuration for Angular samples
* Adjust as necessary for your application needs.
*/
-(function(global) {
-
- // map tells the System loader where to look for things
+(function (global) {
// #docregion paths
- var map = {
- 'app': '/app', // 'dist',
-
- '@angular': '/node_modules/@angular',
- 'angular-in-memory-web-api': '/node_modules/angular-in-memory-web-api',
- 'rxjs': '/node_modules/rxjs'
- };
-
- var packages = {
- '/app': { main: 'main.js', defaultExtension: 'js' },
- 'rxjs': { defaultExtension: 'js' },
- 'angular-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' },
- };
- // #enddocregion paths
-
- var ngPackageNames = [
- 'common',
- 'compiler',
- 'core',
- 'forms',
- 'http',
- 'platform-browser',
- 'platform-browser-dynamic',
- 'router',
- 'router-deprecated',
- 'upgrade',
- ];
-
- // Individual files (~300 requests):
- function packIndex(pkgName) {
- packages['@angular/'+pkgName] = { main: 'index.js', defaultExtension: 'js' };
- }
-
- // Bundled (~40 requests):
- function packUmd(pkgName) {
- packages['@angular/'+pkgName] = { main: '/bundles/' + pkgName + '.umd.js', defaultExtension: 'js' };
- }
-
- var setPackageConfig = System.packageWithIndex ? packIndex : packUmd;
-
- // Add package entries for angular packages
- ngPackageNames.forEach(setPackageConfig);
-
- var config = {
- map: map,
- packages: packages
- }
-
- System.config(config);
+ System.config({
+ paths: {
+ // paths serve as alias
+ 'npm:': '/node_modules/'
+ },
+ map: {
+ app: '/app',
+ // #enddocregion paths
+ // angular bundles
+ '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
+ '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
+ '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
+ '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
+ '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
+ '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
+ '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
+ '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
+ '@angular/upgrade': 'npm:@angular/upgrade/bundles/upgrade.umd.js',
+ // other libraries
+ 'rxjs': 'npm:rxjs',
+ 'angular-in-memory-web-api': 'npm:angular-in-memory-web-api',
+ // #docregion paths
+ },
+ // #enddocregion paths
+ // packages tells the System loader how to load when no filename and/or no extension
+ packages: {
+ 'app': {
+ main: './main.js',
+ defaultExtension: 'js'
+ },
+ rxjs: {
+ defaultExtension: 'js'
+ },
+ 'angular-in-memory-web-api': {
+ main: './index.js',
+ defaultExtension: 'js'
+ }
+ }
+ });
})(this);
diff --git a/public/docs/ts/latest/guide/upgrade.jade b/public/docs/ts/latest/guide/upgrade.jade
index 438ede147e..c5ce0ef1be 100644
--- a/public/docs/ts/latest/guide/upgrade.jade
+++ b/public/docs/ts/latest/guide/upgrade.jade
@@ -1,10 +1,5 @@
include ../_util-fns
-.alert.is-important
- :marked
- This guide is still in the process of being updated to RC5 and it's samples
- may not work correctly.
-
:marked
Having an existing Angular 1 application doesn't mean that we can't
begin enjoying everything Angular 2 has to offer. That's because Angular 2
@@ -28,13 +23,13 @@ include ../_util-fns
make incremental upgrading seamless.
1. [Preparation](#preparation)
- 1. [Following The Angular Style Guide](#following-the-angular-style-guide)
+ 1. [Follow the Angular Style Guide](#follow-the-angular-style-guide)
2. [Using a Module Loader](#using-a-module-loader)
3. [Migrating to TypeScript](#migrating-to-typescript)
4. [Using Component Directives](#using-component-directives)
2. [Upgrading with The Upgrade Adapter](#upgrading-with-the-upgrade-adapter)
1. [How The Upgrade Adapter Works](#how-the-upgrade-adapter-works)
- 2. [Bootstrapping Hybrid Angular 1+2 Applications](#bootstrapping-hybrid-angular-1-2-applications)
+ 2. [Bootstrapping hybrid Angular 1+2 Applications](#bootstrapping-hybrid-angular-1-2-applications)
3. [Using Angular 2 Components from Angular 1 Code](#using-angular-2-components-from-angular-1-code)
4. [Using Angular 1 Component Directives from Angular 2 Code](#using-angular-1-component-directives-from-angular-2-code)
5. [Projecting Angular 1 Content into Angular 2 Components](#projecting-angular-1-content-into-angular-2-components)
@@ -44,7 +39,7 @@ include ../_util-fns
3. [PhoneCat Upgrade Tutorial](#phonecat-upgrade-tutorial)
1. [Switching to TypeScript](#switching-to-typescript)
2. [Installing Angular 2](#installing-angular-2)
- 3. [Bootstrapping A Hybrid 1+2 PhoneCat](#bootstrapping-a-hybrid-1-2-phonecat)
+ 3. [Bootstrapping a hybrid 1+2 PhoneCat](#bootstrapping-a-hybrid-1-2-phonecat)
4. [Upgrading the Phone service](#upgrading-the-phone-service)
5. [Upgrading Components](#upgrading-components)
6. [Switching To The Angular 2 Router And Bootstrap](#switching-to-the-angular-2-router-and-bootstrap)
@@ -61,7 +56,7 @@ include ../_util-fns
and patterns that we can apply to future proof our apps even before we
begin the migration.
- ## Following The Angular Style Guide
+ ## Follow the Angular Style Guide
The [Angular 1 Style Guide](https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md#single-responsibility)
collects patterns and practices that have been proven to result in
@@ -84,6 +79,7 @@ include ../_util-fns
components easy to navigate and find, but will also allow us to migrate
them between languages and frameworks one at a time. In this example application,
each controller, component, service, and filter is in its own source file.
+
* The [Folders-by-Feature Structure](https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md#folders-by-feature-structure)
and [Modularity](https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md#modularity)
rules define similar principles on a higher level of abstraction: Different parts of the
@@ -390,6 +386,26 @@ figure.image-display
as regular Angular 2 inputs and set onto the scope (or controller) when
they change.
+ ## Using the Upgrade Adapter with Angular 2 _NgModules_
+
+ Both Angular 1 and Angular 2 have their own concept of modules
+ to help organize an application into cohesive blocks of funcionality.
+
+ Their details are quite different in architecture and implementation.
+ In Angular 1, you add Angular assets to the `angular.module` property.
+ In Angular 2, you create one or more classes adorned with an `NgModule` decorator
+ that describes Angular assets in metadata. The differences blossom from there.
+
+ In a hybrid application we run both versions of Angular at the same time.
+ That means that we need at least one module each from both Angular 1 and Angular 2.
+ We will give the Angular 2 module to the `UpgradeAdapter` while we use the
+ Angular 1 module for bootstrapping. Let's see how.
+
+.l-sub-section
+ :marked
+ Learn more about Angular 2 modules at the [NgModule guide](ngmodule.html).
+
+:marked
## Bootstrapping Hybrid Angular 1+2 Applications
The first step to upgrading an application using the `UpgradeAdapter` is
@@ -416,28 +432,30 @@ figure.image-display
+makeExample('upgrade-adapter/ts/app/1-bootstrap/app.module.ts', 'bootstrap')
:marked
- To then switch the application into hybrid mode, we must first
- install Angular 2 to the project. Follow the instructions in
- [the QuickStart](../quickstart.html) for some pointers on this.
- When we have Angular 2 installed, we can import and instantiate
- the `UpgradeAdapter`, and then call its `bootstrap` method. It
- is designed to take the exact same arguments as
- [angular.bootstrap](https://docs.angularjs.org/api/ng/function/angular.bootstrap)
- so that it is easy to make the switch:
+ Now introduce Angular 2 to the project. Inspired by instructions in
+ [the QuickStart](../quickstart.html), you can selectively copy in material from the
+ QuickStart github repository.
+
+ Next, create an `app.module.ts` file and add the following `NgModule` class:
+
++makeExample('upgrade-adapter/ts/app/1-2-hybrid-bootstrap/app.module.ts', 'ngmodule')
+
+:marked
+ This bare minimum `NgModule` imports `BrowserModule`, the module every Angular browser-based app must have.
+
+ Import and instantiate the `UpgradeAdapter` with the new `AppModule` and call its `bootstrap` method.
+ That method takes the exact same arguments as [angular.bootstrap](https://docs.angularjs.org/api/ng/function/angular.bootstrap):
+makeExample('upgrade-adapter/ts/app/1-2-hybrid-bootstrap/app.module.ts', 'bootstrap')
:marked
- At this point we'll be running a hybrid Angular 1+2 application! All the
- existing Angular 1 code will work as it always did, but we are now ready
- to run Angular 2 code as well.
+ Congratulations! You're running a hybrid Angular 1+2 application! The
+ existing Angular 1 code works as before _and_ you're ready to run Angular 2 code.
.alert.is-helpful
:marked
- One notable difference between `angular.bootstrap` and
- `upgradeAdapter.bootstrap` is that the latter works *asynchronously*.
- This means that we cannot assume that the application has been instantiated
- immediately after the bootstrap call returns.
+ Note that, unlike `angular.bootstrap`, the `upgradeAdapter.bootstrap` runs *asynchronously*.
+ The application is not launched immediately. Some time must pass after the bootstrap call returns.
:marked
As we begin to migrate components to Angular 2, we'll be using the
@@ -476,16 +494,25 @@ figure
+makeExample('upgrade-adapter/ts/app/downgrade-static/app.module.ts', 'downgradecomponent')
:marked
- What we have here is an Angular 1 directive called `heroDetail`, which we can
+ Because `HeroDetailComponent` is an Angular 2 component, we must also add it to the `declarations` in the `AppModule`.
+
++makeExample('upgrade-adapter/ts/app/downgrade-static/app.module.ts', 'ngmodule')
+.l-sub-section
+ :marked
+ All Angular 2 components, directives and pipes must be declared in an NgModule.
+
+:marked
+ The net resulit is an Angular 1 directive called `heroDetail`, that we can
use like any other directive in our Angular 1 templates.
+makeExample('upgrade-adapter/ts/index-downgrade-static.html', 'usecomponent')
.alert.is-helpful
:marked
- Note that since Angular 1 directives are matched based on their name,
- *the selector metadata of the Angular 2 component is not used in Angular 1*.
- It is matched as an element directive (`restrict: 'E'`) called `heroDetail`.
+ Note that this Angular 1 is an element directive (`restrict: 'E'`) called `heroDetail`.
+ An Angular 1 element directive is matched based on its _name_.
+ *The `selector` metadata of the downgraded Angular 2 component is ignored.*
+
:marked
Most components are not quite this simple, of course. Many of them
@@ -558,11 +585,10 @@ figure
:marked
We can *upgrade* this component to Angular 2 using the `UpgradeAdapter`'s
`upgradeNg1Component` method. It takes the name of an Angular 1 component
- directive and returns an Angular 2 **component class**. When we then
- want to use it from an Angular 2 component, we list it the in the `directives`
- metadata of the component and then just use it in the Angular 2 template:
+ directive and returns an Angular 2 **component class**.
+ Declare it in an `NgModule` as with other Angular 2 components:
-+makeExample('upgrade-adapter/ts/app/upgrade-static/container.component.ts', null, 'container.component.ts')
++makeExample('upgrade-adapter/ts/app/upgrade-static/upgrade_adapter.ts', 'heroupgrade', 'app.module.ts')
.alert.is-helpful
:marked
@@ -731,17 +757,14 @@ figure
+makeExample('upgrade-adapter/ts/app/2-to-1-providers/heroes.ts', null, 'heroes.ts')
:marked
- We can again use the `UpgradeAdapter` for this, but first we need to register `Heroes`
- to the Angular 2 injector itself. In a pure Angular 2 application we would do this
- when we bootstrap the app, as described in the [dependency injection guide](dependency-injection.html#!#providers).
- But since hybrid applications are bootstrapped using the `UpgradeAdapter`, we also
- need to register our Angular 2 providers using `UpgradeAdapter`. It has a method
- called `addProvider` for this purpose.
+ Again, as with Angular 2 components, register the provider with the `NgModule` by adding it to the module's `providers` list.
- Once we've registered the Angular 2 provider, we can turn `Heroes` into an *Angular 1
- factory function* using `upgradeAdapter.downgradeNg2Provider()`. We can
- then plug the factory into an Angular 1 module, at which point we also choose what the
- name of the dependency will be in Angular 1:
++makeExample('upgrade-adapter/ts/app/2-to-1-providers/upgrade_adapter.ts', 'ngmodule', 'app.module.ts')
+
+:marked
+ Now wrap the Angular 2 `Heroes` in an *Angular 1 factory function* using `upgradeAdapter.downgradeNg2Provider()`.
+ and plug the factory into an Angular 1 module.
+ The name of the Angular 1 dependency is up to you:
+makeExample('upgrade-adapter/ts/app/2-to-1-providers/app.module.ts', 'register', 'app.module.ts')
@@ -1033,7 +1056,7 @@ code-example(format="").
development server root path in `package.json` to also point to the project root
instead of `app`:
-+makeJson('upgrade-phonecat-2-hybrid/ts/package.ng1.json', {paths: 'scripts.start'}, 'package.json')
++makeJson('upgrade-phonecat-2-hybrid/ts/package.ng1.json', {paths: 'scripts.start'}, 'package.json (start script)')
:marked
Now we're able to serve everything from the project root to the web browser. But we do *not*
@@ -1058,7 +1081,22 @@ code-example(format="").
+makeExample('upgrade-phonecat-2-hybrid/ts/systemjs.config.1.js', 'paths', 'systemjs.config.js')
:marked
- ## Bootstrapping A Hybrid 1+2 PhoneCat
+ ## Creating the _AppModule_
+
+ Now create the root `NgModule` class called `AppModule`.
+ There is already a file named `app.module.ts` that holds the Angular 1 module.
+ Rename it to `app.module.ng1.ts` and update the corresponding script name in the `index.html` as well.
+ The file contents remain:
+
++makeExample('upgrade-phonecat-2-hybrid/ts/app/app.module.ng1.ts', null, 'app.module.ng1.ts')
+
+:marked
+ Now create a new `app.module.ts` with the minimum `NgModule` class:
+
++makeExample('upgrade-phonecat-2-hybrid/ts/app/app.module.ts', 'bare', 'app.module.ts')
+
+:marked
+ ## Bootstrapping a hybrid 1+2 PhoneCat
What we'll do next is bootstrap the application as a *hybrid application*
that supports both Angular 1 and Angular 2 components. Once we've done that
@@ -1109,32 +1147,19 @@ code-example(format="").
* For loading the details of a single phone into the phone detail component.
We can replace this implementation with an Angular 2 service class, while
- keeping our controllers in Angular 1 land. In the new version we'll just use
- the `Http` service from Angular 2 instead of ngResource.
+ keeping our controllers in Angular 1 land.
+
+ In the new version, we import the Angular 2 HTTP module and call its `Http` service instead of `ngResource`.
- Before the `Http` service is available for injection, we need to register
- it into our application's dependency injector. We should import the `HTTP_PROVIDERS`
- constant in `main.ts`:
+ Re-open the `app.module.ts` file, import and add `HttpModule` to the `imports` array of the `AppModule`:
-+makeExample('upgrade-phonecat-2-hybrid/ts/app/main.ts', 'import-http')
-
-:marked
- In a regular Angular 2 application we would now pass `HTTP_PROVIDERS` into
- the application bootstrap function. But we can't do that in a hybrid
- application such as the one we're working on. That's because the `bootstrap`
- method of `UpgradeAdapter` expects Angular 1 modules as dependencies,
- not Angular 2 providers.
-
- What we must do instead is register `HTTP_PROVIDERS` into the `UpgradeAdapter`
- separately. It has a method called `addProvider` for that purpose:
-
-+makeExample('upgrade-phonecat-2-hybrid/ts/app/main.ts', 'add-http')
++makeExample('upgrade-phonecat-2-hybrid/ts/app/app.module.ts', 'httpmodule', 'app.module.ts')
:marked
Now we're ready to upgrade the Phone service itself. We replace the ngResource-based
service in `phone.service.ts` with a TypeScript class decorated as `@Injectable`:
-+makeExample('upgrade-phonecat-2-hybrid/ts/app/core/phone/phone.service.ts', 'classdef', 'app/core/phone/phone.service.ts')
++makeExample('upgrade-phonecat-2-hybrid/ts/app/core/phone/phone.service.ts', 'classdef', 'app/core/phone/phone.service.ts (skeleton)')(format='.')
:marked
The `@Injectable` decorator will attach some dependency injection metadata
@@ -1154,7 +1179,7 @@ code-example(format="").
The methods now return Observables of type `PhoneData` and `PhoneData[]`. This is
a type we don't have yet, so let's add a simple interface for it:
-+makeExample('upgrade-phonecat-2-hybrid/ts/app/core/phone/phone.service.ts', 'phonedata-interface', 'app/core/phone/phone.service.ts')
++makeExample('upgrade-phonecat-2-hybrid/ts/app/core/phone/phone.service.ts', 'phonedata-interface', 'app/core/phone/phone.service.ts (interface)')(format='.')
:marked
Here's the full, final code for the service:
@@ -1166,24 +1191,17 @@ code-example(format="").
We need to do this for all RxJS operators that we want to use, since Angular 2
does not load all of them by default.
- The new `Phone` service now has the same features that the original, ngResource based
- service did. Now we just need to register the new service into the application, so that
- our Angular 1 components will be able to use it.
+ The new `Phone` service has the same features as the original, `ngResource`-based service.
+ Because it's an Angular 2 service, we register it with the `NgModule` providers:
++makeExample('upgrade-phonecat-2-hybrid/ts/app/app.module.ts', 'phone', 'app.module.ts')
+:marked
`UpgradeAdapter` has a `downgradeNg2Provider` method for the purpose of making
- Angular 2 services available to Angular 1 code. We can use it to plug in our
- `Phone` service:
+ Angular 2 services available to Angular 1 code. Use it to plug in the `Phone` service:
-+makeExample('upgrade-phonecat-2-hybrid/ts/app/main.ts', 'phone-service', 'app/main.ts')
++makeExample('upgrade-phonecat-2-hybrid/ts/app/main.ts', 'phone-service', 'app/main.ts (excerpt)')(format='.')
:marked
- Note that we actually needed to do two registrations here:
-
- 1. Register `Phone` as an **Angular 2 provider** with the `addProvider`
- method. That's the same method that we used earlier for `HTTP_PROVIDERS`.
- 2. Register an **Angular 1 factory** called `phone`, which will be a *downgraded*
- version of the `Phone` Angular 2 service.
-
Now that we are loading `phone.service.ts` through an import that is resolved
by SystemJS, we should **remove the <script> tag** for the service from `index.html`.
This is something we'll do to all our components as we upgrade them. Simultaneously
@@ -1234,69 +1252,72 @@ code-example(format="").
just like the Angular 1 version did.
We now also need to convert the template of this component into Angular 2 syntax.
- In the search controls we need to use Angular 2 syntax for the two `ngModel`s.
- We should also no longer use the `$ctrl` prefix in expressions:
+ The search controls replace the Angular 1 `$ctrl` expressions
+ with Angular 2's two-way `[(ngModel)]` binding syntax:
-+makeExample('upgrade-phonecat-2-hybrid/ts/app/phone-list/phone-list.template.html', 'controls', 'app/phone-list/phone-list.template.html')
++makeExample('upgrade-phonecat-2-hybrid/ts/app/phone-list/phone-list.template.html', 'controls', 'app/phone-list/phone-list.template.html (search controls)')(format='.')
:marked
- In the list we need to replace the `ng-repeat` with an `*ngFor` and the
- `let var of iterable` syntax, which is [described in our
- Template Syntax guide](../guide/template-syntax.html#directives).
- For the images, we can replace `ng-src` with a binding to the standard `src` property.
+ Replace the list's `ng-repeat` with an `*ngFor` as
+ [described in the Template Syntax page](../guide/template-syntax.html#directives).
+ Replace the image tag's `ng-src` with a binding to the native `src` property.
-+makeExample('upgrade-phonecat-2-hybrid/ts/app/phone-list/phone-list.template.html', 'list', 'app/phone-list/phone-list.template.html')
++makeExample('upgrade-phonecat-2-hybrid/ts/app/phone-list/phone-list.template.html', 'list', 'app/phone-list/phone-list.template.html (phones)')(format='.')
:marked
- Another thing that we've done here is that we've removed the use of `filter` and `orderBy` filters,
- and replaced them with a call to the `getPhones()` controller method.
- The built-in Angular filters `filter` and `orderBy` do not exist in Angular 2,
- so we need to do the filtering and sorting ourselves. We could define our own Angular 2
- pipes for this purpose, but in this case it is more convenient to just implement the filtering
- and ordering logic in the component itself. We expect the `getPhones()` method to return a collection
- where the current filtering and ordering has been applied.
+ ### No Angular 2 _filter_ or _orderBy_ filters
+ The built-in Angular 1 `filter` and `orderBy` filters do not exist in Angular 2,
+ so we need to do the filtering and sorting ourselves.
+
+ We replaced the `filter` and `orderBy` filters with bindings to the `getPhones()` controller method,
+ which implements the filtering and ordering logic inside the component itself.
+makeExample('upgrade-phonecat-2-hybrid/ts/app/phone-list/phone-list.component.ts', 'getphones', 'app/phone-list/phone-list.component.ts')
:marked
- In the entrypoint file `main.ts` we're going to plug this component into our application. Instead
- of registering a component, we register a `phoneList` *directive*.
- The directive is a downgraded version of our Angular 2 component, and the `UpgradeAdapter`
- handles the bridging between the two:
+ The new `PhoneListComponent` uses the Angular 2 `ngModel` directive, located in the `FormsModule`.
+ Add the `FormsModule` to `NgModule` imports and declare the new `PhoneListComponent` :
-+makeExample('upgrade-phonecat-2-hybrid/ts/app/main.ts', 'phone-list', 'app/main.ts')
++makeExample('upgrade-phonecat-2-hybrid/ts/app/app.module.ts', 'phonelist', 'app.module.ts')
:marked
- The `` type annotation here is to let the TypeScript compiler
- know that the return value of the downgrade method call will be something that can be
- used as a directive factory.
+ In the entrypoint file `main.ts` we'll plug this component into the Angular 1 module.
+
+ Instead of registering a component, we register a `phoneList` *directive*, a downgraded version of the Angular 2 component.
+ The `UpgradeAdapter` creates the bridge between the two:
- At this point, also remove the <script> tag for the phone list component from `index.html`.
++makeExample('upgrade-phonecat-2-hybrid/ts/app/main.ts', 'phone-list', 'app/main.ts (excerpt)')(format='.')
- Now we can start looking at our other component, which is the one for
- the phone details. Set the contents of `phone-detail.component.ts` as follows:
+:marked
+ The `as angular.IDirectiveFactory` cast tells the TypeScript compiler
+ that the return value of the downgrade method is a directive factory.
+
+ Remove the <script> tag for the phone list component from `index.html`.
+
+ Now set the remaining `phone-detail.component.ts` as follows:
+makeExample('upgrade-phonecat-2-hybrid/ts/app/phone-detail/phone-detail.component.ts', 'initialclass', 'app/phone-detail/phone-detail.component.ts')
:marked
- This is pretty similar to what we did with the phone list. The one new change
- here is the use of `@Inject` for the `$routeParams` dependency. It tells the
- Angular 2 injector what this dependency should map to. We have a dependency called
- `$routeParams` in the Angular 1 injector, where it is provided by the Angular 1 router.
- That is what we were already using when `PhoneDetails` was still an Angular 1 controller.
+ This is similar to the phone list component.
+ The new wrinkle is the `@Inject` decorator that identifies the `$routeParams` dependency.
- The things is though, Angular 1 dependencies are not made automatically available to
- Angular 2 components, so if we were to run this now, it would not work. We need to explicitly
- tell the `UpgradeAdapter` to upgrade `$routeParams` so that it is available for injection in
- Angular 2. We can do it in `main.ts`:
-
-+makeExample('upgrade-phonecat-2-hybrid/ts/app/main.ts', 'routeparams', 'app/main.ts')
+ The Angular 1 injector has an Angular 1 router dependency called `$routeParams`.
+ which was injected into `PhoneDetails` when it was still an Angular 1 controller.
+ We intend to inject it into the new `PhoneDetailsComponent`.
+
+ Unfortunately, Angular 1 dependencies are not automatically available to Angular 2 components.
+ We must use the `UpgradeAdapter` to make the `$routeParams` an Angular 2 provider.
+ Do that in `main.ts`:
++makeExample('upgrade-phonecat-2-hybrid/ts/app/main.ts', 'routeparams', 'app/main.ts ($routeParms)')(format='.')
+.l-sub-section
+ :marked
+ Do not register an upgraded Angular 1 provider in the `NgModule`.
:marked
- We now also need to convert the template of this component into Angular 2 syntax.
- Here is the new template in its entirety:
+ Convert the phone detail component template into Angular 2 syntax as follows:
+makeExample('upgrade-phonecat-2-hybrid/ts/app/phone-detail/phone-detail.template.html', null, 'app/phone-detail/phone-detail.template.html')
@@ -1320,118 +1341,135 @@ code-example(format="").
when we try to refer to properties on undefined objects. We need to be explicit
about cases where this is expected.
+ Add this component to the `NgModule` _declarations_:
+
++makeExample('upgrade-phonecat-2-hybrid/ts/app/app.module.ts', 'phonedetail', 'app.module.ts')
+
:marked
In `main.ts` we'll now register a `phoneDetail` directive instead of a
component. The directive is a downgraded version of the `PhoneDetail` Angular 2
component.
-+makeExample('upgrade-phonecat-2-hybrid/ts/app/main.ts', 'phone-detail', 'app/main.ts')
++makeExample('upgrade-phonecat-2-hybrid/ts/app/main.ts', 'phone-detail', 'app/main.ts (excerpt)')(format='.')
:marked
We should now also remove the phone detail component <script> tag from `index.html`.
- There's one additional step we need to take, which is to upgrade the
- `checkmark` filter that the template is using. We need an Angular 2
- pipe instead of an Angular 1 filter.
+ ### Add the _CheckmarkPipe_
- While there is no upgrade method in the upgrade adapter for filters, we
- can just turn the filter function into a class that fulfills
- the contract for Angular 2 Pipes. The implementation is the same as before.
- It just comes in a different kind of packaging. While changing it, also
- rename the file to `checkmark.pipe.ts`:
+ The Angular 1 directive had a `checkmark` _filter_.
+ Turn that into an Angular 2 **pipe**.
-+makeExample('upgrade-phonecat-2-hybrid/ts/app/core/checkmark/checkmark.pipe.ts', null, 'app/core/checkmark/checkmark.pipe.ts')
+ There is no upgrade adapter method to convert filters into pipes.
+ You won't miss it.
+ It's easy to turn the filter function into an equivalent Pipe class.
+ The implementation is the same as before, repackaged in the `transform` method.
+ Rename the file to `checkmark.pipe.ts` to conform with Angular 2 conventions:
+
++makeExample('upgrade-phonecat-2-hybrid/ts/app/core/checkmark/checkmark.pipe.ts', null, 'app/core/checkmark/checkmark.pipe.ts')(format='.')
:marked
- In the component we should now import and declare our newly created pipe (as well as
- remove the filter <script> tag from `index.html`):
+ Now import and declare the newly created pipe and
+ remove the filter <script> tag from `index.html`:
-+makeExample('upgrade-phonecat-2-hybrid/ts/app/phone-detail/phone-detail.component.ts', 'checkmark-pipe', 'app/phone-detail/phone-detail.component.ts')
++makeExample('upgrade-phonecat-2-hybrid/ts/app/app.module.ts', 'checkmarkpipe', 'app.module.ts')
:marked
## Switching To The Angular 2 Router And Bootstrap
- At this point we've replaced all our Angular 1 application components with
- their Angular 2 counterparts. The application is still bootstrapped as a hybrid,
- but there isn't really any need for that anymore, and we can begin to
- pull out the last remnants of Angular 1.
+ At this point we've replaced all Angular 1 application components with
+ their Angular 2 counterparts.
+
+ The application is still bootstrapped as a hybrid app.
+ There's no need for that anymore.
+ It's time to remove the last remnants of Angular 1 in two final steps:
+ 1. Switch to the Angular 2 router.
+ 1. Bootstrap as a pure Angular 2 app.
- There are just two more things to do: We need to switch the router to
- the Angular 2 one, and then bootstrap the app as a pure Angular 2 app.
+ ### Switch to the Angular 2 router
+ Angular 2 has an [all-new router](router.html).
- Let's do the routing part first. Angular 2 comes with an [all-new router](router.html)
- that we can use for this.
+ Like all routers, it needs a place in the UI to display routed views.
+ The Angular 2 that's the `` and it belongs in a *root component*
+ at the top of the applications component tree.
+
+ We don't yet have such a root component, because the app is still managed as an Angular 1 app.
+ Create a new `app.component.ts` file with the following `AppComponent` class:
- Angular 2 applications all have a *root component*, which, among other
- things, is where we should plug in the router. We don't yet have such a root
- component, because our app is still managed as an Angular 1 app.
- Let's change this now and add an `AppComponent` class into a new file
- `app.component.ts`:
-
-+makeExample('upgrade-phonecat-3-final/ts/app/app.component.ts', null, 'app/app.component.ts')
++makeExample('upgrade-phonecat-3-final/ts/app/app.component.ts', null, 'app/app.component.ts')(format='.')
:marked
- This is a component that plugs in to an `` element on the page,
- and has a simple template that only includes the router outlet component
- of the Angular router. This means that the component just renders the contents
- of the current route and nothing else. The `@RouteConfig` decorator defines
- the Angular 2 counterparts of our two routes. They refer directly to the
- two components.
+ It has a simple template that only includes the ``.
+ This component just renders the contents of the active route and nothing else.
+
+ The selector tells Angular 2 to plug this root component into the ``
+ element on the host web page when the application launches.
- We should put this `` element in the HTML so that the root component
- has something to attach to. It replaces the old Angular 1 `ng-view` directive:
+ Add this `` element to the `index.html`.
+ It replaces the old Angular 1 `ng-view` directive:
-+makeExample('upgrade-phonecat-3-final/ts/index.html', 'appcomponent', 'index.html')
++makeExample('upgrade-phonecat-3-final/ts/index.html', 'appcomponent', 'index.html (body)')(format='.')
:marked
- In the `PhoneDetail` component we now need to change how the phone id parameter
- is received. There will be no more `$routeParams` injection available, because
- that comes from the Angular 1 router. Instead, what we have is a `RouteParams`
- object provided by the Angular 2 router. We use it to obtain the `phoneId` from
- the params:
+ ### Create the _Routing Module_
+ A router needs configuration whether it's the Angular 1 or Angular 2 or any other router.
+
+ The details of Angular 2 router configuration are best left to the [Routing](../router.html) documentation
+ which recommends that you create a `NgModule` dedicated to router configuration
+ (called a _Routing Module_):
+
++makeExample('upgrade-phonecat-3-final/ts/app/app-routing.module.ts', null, 'app/app-routing.module.ts')
+
+:marked
+ This module defines a `routes` object with two routes to the two phone components
+ and a default route for the empty path.
+ It passes the `routes` to the `RouterModule.forRoot` method which does the rest.
+
+ A couple of extra providers enable routing with "hash" URLs such as `#!/phones` instead of the default "push state" strategy.
+
+ Now update the `AppModule` to import this `AppRoutingModule` and also the
+ declare the root `AppComponent`:
+
++makeExample('upgrade-phonecat-3-final/ts/app/app.module.ts', null, 'app/app.module.ts')
+
+:marked
+ The Angular 2 router passes route parameters differently.
+ Correct the `PhoneDetail` component constructor to expect an injected `ActivatedRoute` object.
+ Extract the `phoneId` from the `ActivatedRoute.snapshot.params` and fetch the phone data as before:
+makeExample('upgrade-phonecat-3-final/ts/app/phone-detail/phone-detail.component.ts', null, 'app/phone-detail/phone-detail.component.ts')
+:marked
+ ### Generate links for each phone
+
+ We no longer have to hardcode the links to phone details in the phone list.
+ We can generate them data binding each phone's `id` to the `routerLink` directive
+ and let that directive construct the appropriate URL to the `PhoneDetailComponent`:
+
++makeExample('upgrade-phonecat-3-final/ts/app/phone-list/phone-list.template.html', 'list', 'app/phone-list/phone-list.template.html (list with links)')(format='.')
+.l-sub-section
+ :marked
+ See the [Routing](../router.html) page for details.
:marked
- With that, we're ready to switch the bootstrap method of the application from that
- of the `UpgradeAdapter` to the main Angular 2 `bootstrap`. Let's import it together
- with the router, the new app component, and everything else in `main.ts`
+ ### Bootstrap as an Angular 2 app
-+makeExample('upgrade-phonecat-3-final/ts/app/main.ts', 'imports')
+ You may have noticed one extra `bootstrap` metadata property added to the `AppModule`
++makeExample('upgrade-phonecat-3-final/ts/app/app.module.ts', 'bootstrap', 'app/app.module.ts (bootstrap)')(format='.')
+:marked
+ That tells Angular 2 that it should bootstrap the app with the _root_ `AppComponent` and
+ insert it's view into the host web page.
+
+ Now switch the bootstrap method of the application from the `UpgradeAdapter`
+ to the Angular 2 way.
+ Because this is a browser application, compiled with the Just-in-Time (JiT) compiler,
+ use the `platformBrowserDynamic` function to bootstrap the `AppModule`:
+
++makeExample('upgrade-phonecat-3-final/ts/app/main.ts', null, 'main.ts')
:marked
- We'll now use the regular Angular 2 `bootstrap` function to bootstrap the app
- instead of using `UpgradeAdapter`. The first argument to `bootstrap` is the
- application's root component `AppComponent`, and the second
- is an array of the Angular 2 providers that we want to make available for
- injection. In that array we include all the things we have been registering
- with `upgradeAdapter.addProvider` until now, as well as the providers and
- directives of the router:
+ You are now running a pure Angular 2 application!
-+makeExample('upgrade-phonecat-3-final/ts/app/main.ts', 'bootstrap')
-
-:marked
- We also configure a couple of things for the router here so that the application
- URL paths match exactly those we had in the Angular 1 app: We want the
- hash location strategy with the `!` prefix: `#!/phones`.
-
- At this point we are running a pure Angular 2 application!
-
- But there's actually one more cool thing we can do with the new router.
- We no longer have to hardcode the links to phone details from the phone
- list, because the Angular 2 router is able to generate them for us with
- its `routerLink` directive. We just need to refer to the route names we
- used in the `@RouteConfig`:
-
-+makeExample('upgrade-phonecat-3-final/ts/app/phone-list/phone-list.template.html', 'list', 'app/phone-list/phone-list.template.html')
-
-:marked
- For this to work the directive just needs to be declared in the component:
-
-+makeExample('upgrade-phonecat-3-final/ts/app/phone-list/phone-list.component.ts', 'top')
-
-:marked
- ## Saying Goodbye to Angular 1
+ ## Say Goodbye to Angular 1
It is time to take off the training wheels and let our application begin
its new life as a pure, shiny Angular 2 app. The remaining tasks all have to
@@ -1578,24 +1616,12 @@ code-example(format="").
that use WebDriver's generic URL APIs instead. The first of these is
the redirection spec:
-.alert.is-important
- :marked
- This guide is still in the process of being updated to RC5 and it's samples
- may not work correctly.
-
-//- +makeExample('upgrade-phonecat-3-final/e2e-spec.ts', 'redirect', 'e2e-tests/scenarios.ts')
++makeExample('upgrade-phonecat-3-final/e2e-spec.ts', 'redirect', 'e2e-tests/scenarios.ts')
:marked
And the second is the phone links spec:
-
-.alert.is-important
- :marked
- This guide is still in the process of being updated to RC5 and it's samples
- may not work correctly.
-
-//- +makeExample('upgrade-phonecat-3-final/e2e-spec.ts', 'links', 'e2e-tests/scenarios.ts')
-
++makeExample('upgrade-phonecat-3-final/e2e-spec.ts', 'links', 'e2e-tests/scenarios.ts')
:marked
## Unit Tests
@@ -1666,10 +1692,10 @@ code-example(format="").
:marked
Finally, we need to revisit both of the component tests when we switch to the Angular 2
- router. For the details component we need to provide an Angular 2 `RouteParams` object
+ router. For the details component we need to provide a mock of Angular 2 `ActivatedRoute` object
instead of using the Angular 1 `$routeParams`.
-+makeExample('upgrade-phonecat-3-final/ts/app/phone-detail/phone-detail.component.spec.ts', 'routeparams', 'app/phone-detail/phone-detail.component.spec.ts')
++makeExample('upgrade-phonecat-3-final/ts/app/phone-detail/phone-detail.component.spec.ts', 'activatedroute', 'app/phone-detail/phone-detail.component.spec.ts')
:marked
And for the phone list component we need to set up a few things for the router itself so that