<!DOCTYPE html>
<html>
<html>
<head>
<!-- Set the base href -->
<script>document.write('<base href="' + document.location + '" />');</script>
<title>Router Sample</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles.css">
<!-- Polyfill(s) for older browsers -->
<script src="https://npmcdn.com/core-js/client/shim.min.js"></script>
<script src="https://npmcdn.com/zone.js@0.6.12?main=browser"></script>
<script src="https://npmcdn.com/reflect-metadata@0.1.3"></script>
<script src="https://npmcdn.com/systemjs@0.19.27/dist/system.src.js"></script>
<script src="systemjs.config.js"></script>
<script>
System.import('app')
.catch(function(err){ console.error(err); });
</script>
</head>
<body>
<my-app>loading...</my-app>
</body>
</html>
/* Master Styles */
h1 {
color: #369;
font-family: Arial, Helvetica, sans-serif;
font-size: 250%;
}
h2, h3 {
color: #444;
font-family: Arial, Helvetica, sans-serif;
font-weight: lighter;
}
body {
margin: 2em;
}
body, input[text], button {
color: #888;
font-family: Cambria, Georgia;
}
a {
cursor: pointer;
cursor: hand;
}
button {
font-family: Arial;
background-color: #eee;
border: none;
padding: 5px 10px;
border-radius: 4px;
cursor: pointer;
cursor: hand;
}
button:hover {
background-color: #cfd8dc;
}
button:disabled {
background-color: #eee;
color: #aaa;
cursor: auto;
}
/* Navigation link styles */
nav a {
padding: 5px 10px;
text-decoration: none;
margin-top: 10px;
display: inline-block;
background-color: #eee;
border-radius: 4px;
}
nav a:visited, a:link {
color: #607D8B;
}
nav a:hover {
color: #039be5;
background-color: #CFD8DC;
}
nav a.active {
color: #039be5;
}
/* items class */
.items {
margin: 0 0 2em 0;
list-style-type: none;
padding: 0;
width: 24em;
}
.items li {
cursor: pointer;
position: relative;
left: 0;
background-color: #EEE;
margin: .5em;
padding: .3em 0;
height: 1.6em;
border-radius: 4px;
}
.items li:hover {
color: #607D8B;
background-color: #DDD;
left: .1em;
}
.items li.selected:hover {
background-color: #BBD8DC;
color: white;
}
.items .text {
position: relative;
top: -3px;
}
.items {
margin: 0 0 2em 0;
list-style-type: none;
padding: 0;
width: 24em;
}
.items li {
cursor: pointer;
position: relative;
left: 0;
background-color: #EEE;
margin: .5em;
padding: .3em 0;
height: 1.6em;
border-radius: 4px;
}
.items li:hover {
color: #607D8B;
background-color: #DDD;
left: .1em;
}
.items li.selected {
background-color: #CFD8DC;
color: white;
}
.items li.selected:hover {
background-color: #BBD8DC;
}
.items .text {
position: relative;
top: -3px;
}
.items .badge {
display: inline-block;
font-size: small;
color: white;
padding: 0.8em 0.7em 0 0.7em;
background-color: #607D8B;
line-height: 1em;
position: relative;
left: -1px;
top: -4px;
height: 1.8em;
margin-right: .8em;
border-radius: 4px 0 0 4px;
}
/* everywhere else */
* {
font-family: Arial, Helvetica, sans-serif;
}
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/
/**
* PLUNKER VERSION (based on systemjs.config.js in angular.io)
* System configuration for Angular 2 samples
* Adjust as necessary for your application needs.
*/
(function(global) {
var ngVer = '@2.0.0-rc.5'; // lock in the angular package version; do not let it float to current!
var routerVer = '@3.0.0-rc.1'; // lock router version
var formsVer = '@0.3.0'; // lock forms version
var routerDeprecatedVer = '@2.0.0-rc.2'; // temporarily until we update all the guides
//map tells the System loader where to look for things
var map = {
'app': 'app',
'@angular': 'https://npmcdn.com/@angular', // sufficient if we didn't pin the version
'@angular/router': 'https://npmcdn.com/@angular/router' + routerVer,
'@angular/forms': 'https://npmcdn.com/@angular/forms' + formsVer,
'@angular/router-deprecated': 'https://npmcdn.com/@angular/router-deprecated' + routerDeprecatedVer,
'angular2-in-memory-web-api': 'https://npmcdn.com/angular2-in-memory-web-api', // get latest
'rxjs': 'https://npmcdn.com/rxjs@5.0.0-beta.6',
'ts': 'https://npmcdn.com/plugin-typescript@4.0.10/lib/plugin.js',
'typescript': 'https://npmcdn.com/typescript@1.9.0-dev.20160409/lib/typescript.js',
};
//packages tells the System loader how to load when no filename and/or no extension
var packages = {
'app': { main: 'main.ts', defaultExtension: 'ts' },
'rxjs': { defaultExtension: 'js' },
'angular2-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' },
};
var ngPackageNames = [
'common',
'compiler',
'core',
'http',
'platform-browser',
'platform-browser-dynamic',
'upgrade',
];
// Add map entries for each angular package
// only because we're pinning the version with `ngVer`.
ngPackageNames.forEach(function(pkgName) {
map['@angular/'+pkgName] = 'https://npmcdn.com/@angular/' + pkgName + ngVer;
});
// Add package entries for angular packages
ngPackageNames.concat(['forms', 'router', 'router-deprecated']).forEach(function(pkgName) {
// Bundled (~40 requests):
packages['@angular/'+pkgName] = { main: '/bundles/' + pkgName + '.umd.js', defaultExtension: 'js' };
// Individual files (~300 requests):
//packages['@angular/'+pkgName] = { main: 'index.js', defaultExtension: 'js' };
});
var config = {
// DEMO ONLY! REAL CODE SHOULD NOT TRANSPILE IN THE BROWSER
transpiler: 'ts',
typescriptOptions: {
tsconfig: true
},
meta: {
'typescript': {
"exports": "ts"
}
},
map: map,
packages: packages
};
System.config(config);
})(this);
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true
}
}
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
import { Routes, RouterModule } from '@angular/router';
const appRoutes: Routes = [
{
path: '',
pathMatch: 'full',
redirectTo: 'lazy-named'
},
{
path: 'lazy-named',
loadChildren: 'app/lazy-named/lazy-named.module',
}
];
export const routing = RouterModule.forRoot(appRoutes, {useHash: true});
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `
<h1 class="title">Lazy routes bug</h1>
<nav>
<a routerLink="lazy-named" routerLinkActive="active">Lazy Named</a>
</nav>
<router-outlet></router-outlet>
<problems-component></problems-component>
`
})
export class AppComponent {
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { routing } from './app.routing';
import { SharedModule } from './shared/shared.module';
import { ProblemsComponent } from './problems.component';
@NgModule({
imports: [
BrowserModule,
FormsModule,
routing,
SharedModule
],
declarations: [
AppComponent,
ProblemsComponent
],
bootstrap: [AppComponent]
})
export class AppModule {
}
import { RouterModule } from '@angular/router';
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { Level2Component } from './level2.component';
import { Level1Component } from './level1.component';
import { EmptyComponent } from './empty.component';
import { OutletsComponent } from './outlets.component';
@NgModule({
imports: [
RouterModule
],
declarations: [EmptyComponent, OutletsComponent, Level1Component, Level2Component],
exports: [
CommonModule,
RouterModule,
FormsModule,
EmptyComponent,
OutletsComponent,
Level1Component,
Level2Component
]
})
export class SharedModule {
}
import { Component } from '@angular/core';
@Component({
template: `
<div style="background: rgba(205, 63, 34, 0.18); padding:5px;">
<h4>Level 1</h4>
<router-outlet></router-outlet>
<router-outlet name="outlet_1"></router-outlet>
</div>
`
})
export class Level1Component {
constructor() {}
}
import { Component } from '@angular/core';
@Component({
template: `
<div style="background: rgba(109, 250, 105, 0.3); padding:5px;">
<h5>Level 2</h5>
<empty-component></empty-component>
</div>
`
})
export class Level2Component {
constructor() {}
}
import { Component } from '@angular/core';
@Component({
moduleId: module.id,
selector: 'problems-component',
template: `
<div style="background: #eee; color:#777; padding:5px; margin:5px; ">
<p>Preface:</p>
<ul>
<li>OutletA:Level1 works in 'Default+Named' component</li>
<li>OutletB:Level2 works in 'Default+Named' component</li>
<li>OutletA:Level1/Level2 works in 'Default+Named' component</li>
<li>In 'Default+Named' empty button cleans outlet</li>
<li>This is lazy loaded module. Load children works for primary outlet</li>
</ul>
<p>Bugs in 'Lazy':</p>
<ul>
<li>empty button navigates to 'lazy-named'</li>
</ul>
<p>Bugs in 'Lazy-named':</p>
<ul>
<li>loadChildren for outletA:Level1 not works</li>
<li>loadChildren for outletB:Level2 not works</li>
<li>empty button not works</li>
</ul>
<p>Other bugs:</p>
<ul>
<li>(path:'', component:EmptyComponent) required in children, even if children contains only named outles routes</li>
</ul>
</div>
`
})
export class ProblemsComponent {
constructor() {}
}
import { Router, ActivatedRoute, UrlTree } from '@angular/router';
export abstract class BaseNavigationComponent {
constructor(protected router: Router, protected activatedRoute: ActivatedRoute) {}
openLink(path: string, outlet?: string) {
let urlTree: UrlTree;
if (outlet) {
let outlets = {};
outlets[outlet] = path == '' ? null : path;
urlTree = this.router.createUrlTree([{outlets: outlets}], {relativeTo: this.activatedRoute});
} else {
urlTree = this.router.createUrlTree([path], {relativeTo: this.activatedRoute});
}
console.warn('navigate to ', this.router.serializeUrl(urlTree));
this.router.navigateByUrl(urlTree);
}
}
import { Component } from '@angular/core';
@Component({
moduleId: module.id,
selector: 'outlets-component',
template: `
<div>
<div style="background: rgba(55, 67, 110, 0.25); margin:10px; padding:5px; color:#fff; width:30%; display:inline-block; vertical-align: top">
<span>Primary outlet </span>
<router-outlet></router-outlet>
</div>
<div style="background: rgba(55, 67, 110, 0.25); margin:10px; padding:5px; color:#fff; width:30%; display:inline-block; vertical-align: top">
<span>Outlet A</span>
<router-outlet name="outletA"></router-outlet>
</div>
<div style="background: rgba(55, 67, 110, 0.25); margin:10px; padding:5px; color:#fff; width:30%; display:inline-block; vertical-align: top">
<span>Outlet B</span>
<router-outlet name="outletB"></router-outlet>
</div>
</div>
`
})
export class OutletsComponent {
constructor() {}
}
import { Component } from '@angular/core';
@Component({
moduleId:module.id,
selector:'empty-component',
template: `
<div style="background: rgb(81, 81, 81); padding:2px;">
<h5 style="color:#eee">Empty Component</h5>
</div>
`
})
export class EmptyComponent {
constructor() {}
}
import { Component } from '@angular/core';
import { Router, ActivatedRoute, UrlTree } from '@angular/router';
import { BaseNavigationComponent } from '../base-navigation.component';
@Component({
template: `
<div style="background: rgba(200,150,0,0.3); padding:5px;">
<h2>Lazy Named Outlet Component</h2>
<div>
<span>Primary:</span>
<button (click)="openLink('')">Empty</button>
<button (click)="openLink('level1')">Level1</button>
<button (click)="openLink('level2')">Level2</button>
<!--<button (click)="openLink('level1/level2')">Level1/Level2</button>-->
</div>
<div style="padding-top: 5px">
<span>Outlet A:</span>
<button (click)="openLink('', 'outletA')">Empty</button>
<button (click)="openLink('level1', 'outletA')">Level1</button>
<button (click)="openLink('level2', 'outletA')">Level2</button>
<!--<button (click)="openLink('level1/level2', 'outletA')">Level1/Level2</button>-->
</div>
<div style="padding-top: 5px">
<span>Outlet B:</span>
<button (click)="openLink('', 'outletB')">Empty</button>
<button (click)="openLink('level1', 'outletB')">Level1</button>
<button (click)="openLink('level2', 'outletB')">Level2</button>
<!--<button (click)="openLink('level1/level2', 'outletB')">Level1/Level2</button>-->
</div>
<outlets-component></outlets-component>
</div>
`
})
export class LazyNamedComponent extends BaseNavigationComponent {
constructor(router: Router, activatedRoute: ActivatedRoute) {
super(router, activatedRoute);
}
}
import { NgModule } from '@angular/core';
import { SharedModule } from '../shared/shared.module';
import { LazyNamedComponent } from './lazy-named.component';
import { lazyNamedRouting } from './lazy-named.routing';
@NgModule({
imports: [
SharedModule,
lazyNamedRouting
],
declarations: [LazyNamedComponent],
exports: [LazyNamedComponent]
})
export default class LazyNamedModule {
}
import { Routes, RouterModule } from '@angular/router';
import { LazyNamedComponent } from './lazy-named.component';
import { EmptyComponent } from '../shared/empty.component';
const outletARoutes: Routes = [
{
path: 'level1',
outlet: 'outletA',
loadChildren: 'app/lazy-named/lazy-named-level1/lazy-named-level1.module'
},
{
path: 'level2',
outlet: 'outletA',
loadChildren: 'app/lazy-named/lazy-named-level2/lazy-named-level2.module'
}
];
const outletBRoutes: Routes = [
{
path: 'level1',
outlet: 'outletB',
loadChildren: 'app/lazy-named/lazy-named-level1/lazy-named-level1.module'
},
{
path: 'level2',
outlet: 'outletB',
loadChildren: 'app/lazy-named/lazy-named-level2/lazy-named-level2.module'
}
];
const lazyNamedRoutes: Routes = [
{
path: '',
component: LazyNamedComponent,
children: [
{
path: '',
component: EmptyComponent
},
{
path: 'level1',
loadChildren: 'app/lazy-named/lazy-named-level1/lazy-named-level1.module'
},
{
path: 'level2',
loadChildren: 'app/lazy-named/lazy-named-level2/lazy-named-level2.module'
},
...outletARoutes,
...outletBRoutes
]
}
];
export const lazyNamedRouting = RouterModule.forChild(lazyNamedRoutes);
import { NgModule } from '@angular/core';
import { SharedModule } from '../../shared/shared.module';
import { lazyNamedLevel1Routing } from './lazy-named-level1.routing';
@NgModule({
imports: [
SharedModule,
lazyNamedLevel1Routing
],
declarations: [],
providers: []
})
export default class LazyNamedLevel1Module {
}
import { Routes, RouterModule } from '@angular/router';
import { Level1Component } from '../../shared/level1.component';
const lazyNamedLevel1Routes: Routes = [
{
path: '',
component: Level1Component
}
];
export const lazyNamedLevel1Routing = RouterModule.forChild(lazyNamedLevel1Routes);
import { NgModule } from '@angular/core';
import { SharedModule } from '../../shared/shared.module';
import { lazyNamedLevel2Routing } from './lazy-named-level2.routing';
@NgModule({
imports: [
SharedModule,
lazyNamedLevel2Routing
],
declarations: [],
providers: []
})
export default class LazyNamedLevel2Module {
}
import { Routes, RouterModule } from '@angular/router';
import { Level2Component } from '../../shared/level2.component';
const lazyNamedLevel2Routes: Routes = [
{
path: '',
component: Level2Component
}
];
export const lazyNamedLevel2Routing = RouterModule.forChild(lazyNamedLevel2Routes);