<!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';