<!DOCTYPE html>
<html>
<head>
<base href="." />
<title>Ng 5 resolution based routing</title>
<!-- polyfill(s) for older browsers -->
<script src="https://unpkg.com/core-js/client/shim.min.js"></script>
<script src="https://unpkg.com/zone.js@0.8.16?main=browser"></script>
<!--<script src="https://unpkg.com/reflect-metadata@0.1.10"></script>-->
<script src="https://unpkg.com/systemjs@0.20.18/dist/system.src.js"></script>
<script src="https://unpkg.com/web-animations-js@2.3.1"></script>
<script src="systemjs.config.js"></script>
<script>
System.import('app').catch(function (err) { console.error(err); });
</script>
</head>
<body>
<app-root>
<h1 class="loading">
Loading...
<img *ngIf="loading" src="data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA==" />
</h1>
</app-root>
</body>
</html>
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `<router-outlet></router-outlet>`
})
export class AppComponent {
title = 'app';
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { FormsModule } from '@angular/forms';
import { FlexLayoutModule } from '@angular/flex-layout';
import { SharedModule } from './shared/shared.module';
import { AppComponent } from './app.component';
import { ListDesktopComponent } from './components/index';
import { ListMobileComponent } from './components/index';
import { ValueDesktopComponent } from './components/index';
import { ValueMobileComponent } from './components/index';
import { AppRoutingModule } from './app.routing';
@NgModule({
imports: [
BrowserModule,
FormsModule,
BrowserAnimationsModule,
FlexLayoutModule,
SharedModule,
AppRoutingModule
],
declarations: [
AppComponent,
ListDesktopComponent,
ListMobileComponent,
ValueDesktopComponent,
ValueMobileComponent
],
entryComponents: [
ListDesktopComponent,
ListMobileComponent,
ValueDesktopComponent,
ValueMobileComponent
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
(function (global) {
var angVer = '5.0.0-beta.6';
System.config({
transpiler: 'ts',
typescriptOptions: {
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"lib": [ "es2015", "dom" ],
"module": "commonjs",
"moduleResolution": "node",
"noImplicitAny": true,
"sourceMap": true,
"suppressImplicitAnyIndexErrors": true,
"target": "es5"
},
meta: {
'typescript': {
"exports": "ts"
}
},
paths: {
'npm:': 'https://unpkg.com/',
'gh:': 'https://raw.githubusercontent.com/'
},
map: {
"app": "app",
"rxjs": "npm:rxjs@5.4.3",
"ts": "npm:plugin-typescript@7.1.0/lib/plugin.js",
"typescript": "npm:typescript@2.4.2/lib/typescript.js",
"@angular/core": "npm:@angular/core@" + angVer + "/bundles/core.umd.js",
"@angular/common": "npm:@angular/common@" + angVer + "/bundles/common.umd.js",
"@angular/compiler": "npm:@angular/compiler@" + angVer + "/bundles/compiler.umd.js",
"@angular/platform-browser": "npm:@angular/platform-browser@" + angVer + "/bundles/platform-browser.umd.js",
"@angular/platform-browser-dynamic": "npm:@angular/platform-browser-dynamic@" + angVer + "/bundles/platform-browser-dynamic.umd.js",
"@angular/http": "npm:@angular/http@" + angVer + "/bundles/http.umd.js",
"@angular/router": "npm:@angular/router@" + angVer + "/bundles/router.umd.js",
"@angular/forms": "npm:@angular/forms@" + angVer + "/bundles/forms.umd.js",
"@angular/animations": "npm:@angular/animations@" + angVer + "/bundles/animations.umd.js",
"@angular/animations/browser": "npm:@angular/animations@" + angVer + "/bundles/animations-browser.umd.js",
"@angular/platform-browser/animations": "npm:@angular/platform-browser@" + angVer + "/bundles/platform-browser-animations.umd.js",
"@angular/flex-layout": "npm:@angular/flex-layout@2.0.0-beta.9"
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
app: {
main: './main.ts',
defaultExtension: 'ts'
},
rxjs: {
defaultExtension: 'js'
}
}
});
if (!global.noBootstrap) { bootstrap(); }
// Bootstrap the `AppModule`(skip the `app/main.ts` that normally does this)
function bootstrap() {
// Stub out `app/main.ts` so System.import('app') doesn't fail if called in the index.html
System.set(System.normalizeSync('app/main.ts'), System.newModule({ }));
// bootstrap and launch the app (equivalent to standard main.ts)
Promise.all([
System.import('@angular/platform-browser-dynamic'),
System.import('app/app.module')
])
.then(function (imports) {
var platform = imports[0];
var app = imports[1];
platform.platformBrowserDynamic().bootstrapModule(app.AppModule);
})
.catch(function(err){ console.error(err); });
}
})(this);
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ReversePipe, ResolutionService, DataService } from './index';
@NgModule({
imports: [
CommonModule
],
declarations: [
ReversePipe
],
exports: [
CommonModule,
ReversePipe
],
providers: [
ResolutionService,
DataService
]
})
export class SharedModule {}
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { SharedModule } from '../shared/shared.module';
import { LazyListDesktopComponent } from './components/index';
import { LazyListMobileComponent } from './components/index';
import { LazyValueDesktopComponent } from './components/index';
import { LazyValueMobileComponent } from './components/index';
import { LazyRoutingModule } from './lazy.routing';
import { lazyRouting } from './lazy.routing';
@NgModule({
imports: [
CommonModule,
SharedModule,
lazyRouting
],
declarations: [
LazyListDesktopComponent,
LazyListMobileComponent,
LazyValueDesktopComponent,
LazyValueMobileComponent
],
entryComponents: [
LazyListDesktopComponent,
LazyListMobileComponent,
LazyValueDesktopComponent,
LazyValueMobileComponent
],
providers: []
})
export class LazyModule {}
import { NgModule, ModuleWithProviders } from '@angular/core';
import { Routes, Router, RouterModule } from '@angular/router';
import { LazyListDesktopComponent } from './components/index';
import { LazyListMobileComponent } from './components/index';
import { LazyValueDesktopComponent } from './components/index';
import { LazyValueMobileComponent } from './components/index';
import { ResolutionService } from '../shared/index';
export const lazyAppDesktopRoutes: Routes = [
{
path: '',
component: LazyListDesktopComponent,
children: [
{
path: 'item/:id',
component: LazyValueDesktopComponent
}
]
}
];
export const lazyAppMobileRoutes: Routes = [
{
path: '',
component: LazyListMobileComponent
},
{
path: 'item/:id',
component: LazyValueMobileComponent
}
];
export const lazyRouting: ModuleWithProviders = RouterModule.forChild(lazyAppMobileRoutes);
@NgModule({
imports: [
RouterModule.forChild([])
],
exports: [
RouterModule
]
})
export class LazyRoutingModule {
private previousWidth: number;
constructor(
private router: Router,
private resolutionService: ResolutionService
) {
this.previousWidth = -999;
resolutionService.width.subscribe(width => {
this.doReRoute(width);
});
}
doReRoute(width: number) {
const MOBILE_WIDTH = 991; // bootstrap grid break point for tablet view
if (width !== this.previousWidth) {
if (width < MOBILE_WIDTH && (this.previousWidth >= MOBILE_WIDTH || this.previousWidth === -999)) {
this.router.resetConfig(lazyAppMobileRoutes);
this.router.navigate([]);
} else if (width >= MOBILE_WIDTH && this.previousWidth < MOBILE_WIDTH) {
this.router.resetConfig(lazyAppDesktopRoutes);
this.router.navigate([]);
}
this.previousWidth = width;
}
}
}
import { NgModule } from '@angular/core';
import { Routes, Router, RouterModule } from '@angular/router';
import { ListDesktopComponent } from './components/index';
import { ListMobileComponent } from './components/index';
import { ValueDesktopComponent } from './components/index';
import { ValueMobileComponent } from './components/index';
import { ResolutionService } from './shared/index';
export const appDesktopRoutes: Routes = [
{
path: '',
component: ListDesktopComponent,
children: [
{
path: 'item/:id',
component: ValueDesktopComponent
}
]
},
{ path: 'lazy',
loadChildren: './app/lazy/lazy.module#LazyModule',
}
];
export const appMobileRoutes: Routes = [
{
path: '',
component: ListMobileComponent
},
{
path: 'item/:id',
component: ValueMobileComponent
},
{ path: 'lazy',
loadChildren: './app/lazy/lazy.module#LazyModule',
}
];
@NgModule({
imports: [
RouterModule.forRoot([])
],
exports: [
RouterModule
]
})
export class AppRoutingModule {
private previousWidth: number;
constructor(
private router: Router,
private resolutionService: ResolutionService
) {
this.previousWidth = -999;
resolutionService.width.subscribe(width => {
this.doReRoute(width);
});
}
doReRoute(width: number) {
const MOBILE_WIDTH = 500; // magic number resolution breakpoint
if (width !== this.previousWidth) {
if (width < MOBILE_WIDTH && (this.previousWidth >= MOBILE_WIDTH || this.previousWidth === -999)) {
this.router.resetConfig(appMobileRoutes);
this.router.navigate([]);
} else if (width >= MOBILE_WIDTH && this.previousWidth < MOBILE_WIDTH) {
this.router.resetConfig(appDesktopRoutes);
this.router.navigate([]);
}
this.previousWidth = width;
}
}
}
import { Injectable } from '@angular/core';
@Injectable()
export class DataService {
getList() {
return [
{
key: '1',
value: 'some value 1'
},
{
key: '2',
value: 'some value 2'
},
{
key: '3',
value: 'some value 3'
},
{
key: '4',
value: 'some value 4'
}
];
}
getItemByKey(key) {
return this.getList().filter(item => item.key === key)[0];
}
}
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'reverse',
pure: false
})
export class ReversePipe implements PipeTransform {
transform (values: any) {
if (values) {
return values.reverse();
}
}
}
import { Injectable, NgZone } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
@Injectable()
export class ResolutionService {
constructor(ngZone: NgZone) {
// On resize
window.onresize = (e) => {
ngZone.run(() => {
this.width.next(window.innerWidth);
});
};
}
width: BehaviorSubject<number> = new BehaviorSubject<number>(window.innerWidth);
getWidth() {
return window.innerWidth;
}
}
export * from './data.service';
export * from './resolution.service';
export * from './reverse.pipe';
import { Component } from '@angular/core';
import { DataService } from '../shared/index';
@Component({
selector: 'app-listdesk',
template: `
DESKTOP EAGER
<ul>
<li *ngFor="let item of items" [routerLink]="['/item',item.key ]" style="cursor: pointer" >
{{item.key}}
</li>
</ul>
<a [routerLink]="['/lazy']" style="font-weight: bold;">lazy</a>
<br />
<br />
<router-outlet></router-outlet>
`
})
export class ListDesktopComponent {
items = [];
selectedItem;
constructor(
private dataService: DataService,
) {
this.items = dataService.getList();
this.selectedItem = this.items[0].key;
}
}
import { Component } from '@angular/core';
import { DataService } from '../shared/index';
@Component({
selector: 'app-listmobile',
template: `
MOBILE EAGER
<ul style="color: red">
<li *ngFor="let item of items | reverse" [routerLink]="['/item',item.key ]" style="cursor: pointer" >
{{item.key}}
</li>
</ul>
<a [routerLink]="['/lazy']" style="font-weight: bold;">lazy</a>
`
})
export class ListMobileComponent {
items = [];
selectedItem;
constructor(
private dataService: DataService,
) {
this.items = dataService.getList();
this.selectedItem = this.items[0].key;
}
}
import { Component } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { DataService } from '../shared/index';
@Component({
selector: 'app-valuedesk',
template: `
<div>DESKTOP COMP</div>
<div>
Key : {{data.key}} <br/>
Value: {{data.value}}
</div>
<br/>
<a [routerLink]="['/']" style="font-weight: bold;">clear value</a>
`
})
export class ValueDesktopComponent {
data;
constructor(private dataService: DataService, route: ActivatedRoute) {
route.params.subscribe(param => {
this.getData(param['id']);
});
}
getData(id) {
this.data = this.dataService.getItemByKey(id);
}
}
import { Component } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { DataService } from '../shared/index';
@Component({
selector: 'app-valuemobile',
template: `
<div>MOBILE COMP</div>
<div>
Key : {{data.key}} <br/>
Value: {{data.value}}
</div>
<br/>
<a [routerLink]="['/']" style="font-weight: bold;">back</a>
`
})
export class ValueMobileComponent {
data;
constructor(private dataService: DataService, route: ActivatedRoute) {
route.params.subscribe(param => {
this.getData(param['id']);
});
}
getData(id) {
this.data = this.dataService.getItemByKey(id);
}
}
export * from './list_desktop.component';
export * from './list_mobile.component';
export * from './value_desktop.component';
export * from './value_mobile.component';
import { Component } from '@angular/core';
import { DataService } from '../../shared/index';
@Component({
selector: 'app-lazylistdesk',
template: `
DESKTOP LAZY
<ul style="color: darkgreen">
<li *ngFor="let item of items" [routerLink]="['/lazy/item',item.key ]" style="cursor: pointer" >
{{item.key}}
</li>
</ul>
<a [routerLink]="['/']" style="font-weight: bold;">eager</a>
<br />
<br />
<router-outlet></router-outlet>
`
})
export class LazyListDesktopComponent {
items = [];
selectedItem;
constructor(
private dataService: DataService,
) {
this.items = dataService.getList();
this.selectedItem = this.items[0].key;
}
}
import { Component } from '@angular/core';
import { DataService } from '../../shared/index';
@Component({
selector: 'app-lazylistmobile',
template: `
MOBILE LAZY
<ul style="color: orange">
<li *ngFor="let item of items | reverse" [routerLink]="['/lazy/item',item.key ]" style="cursor: pointer" >
{{item.key}}
</li>
</ul>
<a [routerLink]="['/']" style="font-weight: bold;">eager</a>
`
})
export class LazyListMobileComponent {
items = [];
selectedItem;
constructor(
private dataService: DataService,
) {
this.items = dataService.getList();
this.selectedItem = this.items[0].key;
}
}
import { Component } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { DataService } from '../../shared/index';
@Component({
selector: 'app-lazyvaluedesk',
template: `
<div>DESKTOP COMP</div>
<div>
Key : {{data.key}} <br/>
Value: {{data.value}}
</div>
<br/>
<a [routerLink]="['/lazy']" style="font-weight: bold;">clear value</a>
`
})
export class LazyValueDesktopComponent {
data;
constructor(private dataService: DataService, route: ActivatedRoute) {
route.params.subscribe(param => {
this.getData(param['id']);
});
}
getData(id) {
this.data = this.dataService.getItemByKey(id);
}
}
import { Component } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { DataService } from '../../shared/index';
@Component({
selector: 'app-lazyvaluemobile',
template: `
<div>MOBILE COMP</div>
<div>
Key : {{data.key}} <br/>
Value: {{data.value}}
</div>
<br/>
<a [routerLink]="['/lazy']" style="font-weight: bold;">back</a>
`
})
export class LazyValueMobileComponent {
data;
constructor(private dataService: DataService, route: ActivatedRoute) {
route.params.subscribe(param => {
this.getData(param['id']);
});
}
getData(id) {
this.data = this.dataService.getItemByKey(id);
}
}
export * from './lazy_list_desktop.component';
export * from './lazy_list_mobile.component';
export * from './lazy_value_desktop.component';
export * from './lazy_value_mobile.component';