<!DOCTYPE html>
<html>

  <head>
    <base href="." />
    <script type="text/javascript" charset="utf-8">
      window.AngularVersionForThisPlunker = 'latest'
    </script>
    <title>angular playground</title>
    <link rel="stylesheet" href="style.css" />
    <script src="https://unpkg.com/core-js@2.4.1/client/shim.min.js"></script>
    <script src="https://unpkg.com/zone.js/dist/zone.js"></script>
    <script src="https://unpkg.com/zone.js/dist/long-stack-trace-zone.js"></script>
    <script src="https://unpkg.com/reflect-metadata@0.1.3/Reflect.js"></script>
    <script src="https://unpkg.com/systemjs@0.19.31/dist/system.js"></script>
    <script src="config.js"></script>
    <script>
    System.import('app')
      .catch(console.error.bind(console));
  </script>
  </head>

  <body>
    <my-app>
    loading...
  </my-app>
  </body>

</html>
/* Styles go here */

### simulate configuring http url async
For an angular application which is deployed inhouse to several customers,
the application has to figure out, where the backend server exists.

Setting the url in the environment was not useful, as each customer needs
his own url and this would end up in big build scripts.

Also the customer could not reorganize the server names on his own, without 
breaking the application if he chooses to change the server name.

So we tried to be clever and to figure out where the server might be in
loading a configuration file from an untouched json file in the application.
Or if there is no such file, try to test if the angular app and the backend are
on the same server and use that value as base url.

First we had this in the init method of the app component. This worked well
on our developer machines, but not on slow internet connections, as we did
our first http calls to the backend before the result with the correct url
was returned.

We fixed this issue with having a cached url which is put into an observable,
if exist, otherwise an observable fetching the right url is called first, 
before any http call to the backend is made.

This plunker should simulate an http call which has to wait until a url is found
and after that, all other clicks to the button use the cached url.

This solution also works, if you hit the button before the url was found. Then
the find url process is used for that http call as well.
var angularVersion;
if(window.AngularVersionForThisPlunker === 'latest'){
  angularVersion = ''; //picks up latest
}
else {
  angularVersion = '@' + window.AngularVersionForThisPlunker;
}

System.config({
  //use typescript for compilation
  transpiler: 'typescript',
  //typescript compiler options
  typescriptOptions: {
    emitDecoratorMetadata: true
  },
  paths: {
    'npm:': 'https://unpkg.com/'
  },
  //map tells the System loader where to look for things
  map: {
    
    'app': './src',
    '@angular/core': 'npm:@angular/core'+ angularVersion + '/bundles/core.umd.js',
    '@angular/common': 'npm:@angular/common' + angularVersion + '/bundles/common.umd.js',
    '@angular/compiler': 'npm:@angular/compiler' + angularVersion  + '/bundles/compiler.umd.js',
    '@angular/platform-browser': 'npm:@angular/platform-browser' + angularVersion + '/bundles/platform-browser.umd.js',
    '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic' + angularVersion + '/bundles/platform-browser-dynamic.umd.js',
    '@angular/http': 'npm:@angular/http' + angularVersion + '/bundles/http.umd.js',
    '@angular/router': 'npm:@angular/router' + angularVersion +'/bundles/router.umd.js',
    '@angular/forms': 'npm:@angular/forms' + angularVersion + '/bundles/forms.umd.js',
    '@angular/animations': 'npm:@angular/animations' + angularVersion + '/bundles/animations.umd.js',
    '@angular/platform-browser/animations': 'npm:@angular/platform-browser' + angularVersion + '/bundles/platform-browser-animations.umd.js',
    '@angular/animations/browser': 'npm:@angular/animations' + angularVersion + '/bundles/animations-browser.umd.js',
    
    '@angular/core/testing': 'npm:@angular/core' + angularVersion + '/bundles/core-testing.umd.js',
    '@angular/common/testing': 'npm:@angular/common' + angularVersion + '/bundles/common-testing.umd.js',
    '@angular/compiler/testing': 'npm:@angular/compiler' + angularVersion + '/bundles/compiler-testing.umd.js',
    '@angular/platform-browser/testing': 'npm:@angular/platform-browser' + angularVersion + '/bundles/platform-browser-testing.umd.js',
    '@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic' + angularVersion + '/bundles/platform-browser-dynamic-testing.umd.js',
    '@angular/http/testing': 'npm:@angular/http' + angularVersion + '/bundles/http-testing.umd.js',
    '@angular/router/testing': 'npm:@angular/router' + angularVersion + '/bundles/router-testing.umd.js',
    'tslib': 'npm:tslib@1.6.1',
    'rxjs': 'npm:rxjs',
    'typescript': 'npm:typescript@2.2.1/lib/typescript.js'
  },
  //packages defines our app package
  packages: {
    app: {
      main: './main.ts',
      defaultExtension: 'ts'
    },
    rxjs: {
      defaultExtension: 'js'
    }
  }
});
//main entry point
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {AppModule} from './app';

platformBrowserDynamic().bootstrapModule(AppModule)
//our root app component
import {Component, NgModule, VERSION} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import { Observable } from 'rxjs/Rx';

@Component({
  selector: 'my-app',
  template: `
  <div>
    <h2>Hello {{name}}</h2>
    <button (click)="loadSomeStuff()">Simulate Http Call</button>
    <hr>
    <ol>
    <li *ngFor="let entry of history">{{entry}}</li>
    </ol>
  </div>
  `,
  styles: [`
  ol {
    list-style-type: number;
  }
  ol li {
    font: 1em Helvetica, Verdana, sans-serif;
    margin: 0;
    padding: 0;
  }
  `]
})
export class App {
  
  history: string[] = [];
  name: string;
  cached: string;

  constructor() {
    this.name = `Angular! v${VERSION.full}`
  }
  
   loadSomeStuff() {
    this.addToHistory('START - call method using http');
    this.someHttpAction();
    this.addToHistory('just after method with http is called');
  }

  someHttpAction(): void {
    this.findUrl().mergeMap((urlString) => this.httpCall(1).map(response => {
      this.addToHistory('http result mapping for ' + urlString);
    })).subscribe(
      value => this.addToHistory('value received from http'),
      error => this.addToHistory('error received from http'),
      () => this.addToHistory('END - http call completed')
    )
  }

  findUrl(): Observable<string> {
    if (this.cached) {
      this.addToHistory('url is already known so use cached url');
      return Observable.of(this.cached);
    } else {
      this.addToHistory('try to get config from http, this should take 5 seconds');
      return this.httpCall(5).map(response => {
        this.addToHistory('url found, now cache url');
        this.cached = 'http://some.url/cached';
        return 'http://some.url/';
      });
    }
  }
  
  httpCall(seconds: number): Observable<number> {
    return Observable.timer(1000 * seconds).take(1);
  }

  addToHistory(text: string) {
    this.history.push(text);
  }
}

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ App ],
  bootstrap: [ App ]
})
export class AppModule {}