<!DOCTYPE html>
<html>

  <head>
    <title>angular2 playground</title>
    <link rel="stylesheet" href="style.css" />
    <script src="https://code.angularjs.org/2.0.0-beta.17/angular2-polyfills.js"></script>
    <script src="https://code.angularjs.org/tools/system.js"></script>
    <script src="https://code.angularjs.org/tools/typescript.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 */

### Angular2 Starter Plunker - Typescript - RC.0

A simple plunker demonstrating Angular2 usage:
- Uses SystemJS + TypeScript to compile on the fly
- Includes binding, directives, http, pipes, and DI usage.
System.config({
  //use typescript for compilation
  transpiler: 'typescript',
  //typescript compiler options
  typescriptOptions: {
    emitDecoratorMetadata: true
  },
  //map tells the System loader where to look for things
  map: {
    app: "./src",
    '@angular': 'https://npmcdn.com/@angular',
    'rxjs': 'https://npmcdn.com/rxjs@5.0.0-beta.6'
  },
  //packages defines our app package
  packages: {
    app: {
      main: './main.ts',
      defaultExtension: 'ts'
    },
    '@angular/core': {
      main: 'core.umd.js',
      defaultExtension: 'js'
    },
    '@angular/compiler': {
      main: 'compiler.umd.js',
      defaultExtension: 'js'
    },
    '@angular/common': {
      main: 'common.umd.js',
      defaultExtension: 'js'
    },
    '@angular/platform-browser-dynamic': {
      main: 'platform-browser-dynamic.umd.js',
      defaultExtension: 'js'
    },
    '@angular/platform-browser': {
      main: 'platform-browser.umd.js',
      defaultExtension: 'js'
    },
    '@angular/router-deprecated': {
      main: 'router-deprecated.umd.js',
      defaultExtension: 'js'
    },
    rxjs: {
      defaultExtension: 'js'
    }
  }
});
//main entry point
import {bootstrap} from '@angular/platform-browser-dynamic';
import {App} from './app';
import {APP_BASE_HREF} from '@angular/common';
import {provide} from '@angular/core';
import { ROUTER_PROVIDERS } from '@angular/router-deprecated'

bootstrap(App, [ ROUTER_PROVIDERS,provide(APP_BASE_HREF, {useValue : '/' })])
  .catch(err => console.error(err));
//our root app component
import {Component} from '@angular/core'
import {RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS } from '@angular/router-deprecated'
import {PageOneComponent} from './PageOneComponent'
import {PageTwoComponent} from './PageTwoComponent'

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>{{name}}</h2>
      <p>Not all components are destroyed properly when routing to a new page.</p>
      <p><b>Steps to reproduce:</b></p>
      <ol>
      <li>Click on Page One to route to PageOne Component</li>
      <li>Open your browser console</li>
      <li>Click anywhere in the preview to see click event logs</li>
      <li>Click on PageTwo link</li>
      <li>At this point all 3 child components in pageOne should have been destroyed.</li>
      <li>Click anywhere in the preview, u can still see the click event firing. You shouldn't.</li>
      </ol>
      
      <p><b>Expected:</b> 3 TestComponents to be destroyed.</p>
      
      <p><b>Result:</b> For some reason only 2 of the 3 child components (TestComponent) in PageOne are destroyed.</p>
      
      <div>
      <a [routerLink]="['PageOne']">PageOne</a> | <a [routerLink]="['PageTwo']">PageTwo</a>
      </div>
      <router-outlet></router-outlet>
    </div>
  `,
  directives: [ROUTER_DIRECTIVES],
  providers: [ROUTER_PROVIDERS]
})

@RouteConfig([
  {
    path: '/pageOne',
    name: 'PageOne',
    component: PageOneComponent
  },
  {
    path: '/pageTwo',
    name: 'PageTwo',
    component:  PageTwoComponent
  }
])

export class App {
  
  constructor() {
    this.name = 'Angular 2';
  }
  
  
}
import {Directive, ElementRef, Input, Output, EventEmitter} from '@angular/core';

@Directive({
  selector: '[docClick]',
  host: {
    // Track mouse events at the global level.
    "(document: click)": "handleEvent( $event )",
    "(document: mousedown)": "handleEvent( $event )",
    "(document: mouseup)": "handleEvent( $event )"
  }
})
export class DocClickDirective {

  /**
   * <div docClick (customClick)="onCustomClick()"></div>
   * @type {EventEmitter}
   */
  @Output() customClick:EventEmitter<any> = new EventEmitter();
  @Output() mousedownOutside:EventEmitter<any> = new EventEmitter();
  @Output() mouseupOutside:EventEmitter<any> = new EventEmitter();

  /**
   * Hold a reference to the outsideElement click element.
   */
  private _elementRef:ElementRef;


  constructor(el: ElementRef) {
    this._elementRef = el;
  }


  ngOnDestroy() {
    //console.log('destroyed docClickDirective');
  }

  /**
   * Global mouse event handler
   * @param globalEvent
   */
  public handleEvent( globalEvent ) {
    
    // We are only concerned with mouse events that were triggered
  // outside of the current host component.
  if ( this.eventTriggeredInsideHost( globalEvent ) ) {
    return;
  }
    
     setTimeout( () => {
      console.log('click event still here..');
      this["customClick" ].emit( globalEvent );
     },0);
  }
  
  
  /**
   * I determine if the given event was triggered somewhere within the
   * local host component DOM (Document Object Model) tree.
   * @param event
   * @returns {boolean}
   */
  private eventTriggeredInsideHost( event ) {
  var current = event.target;
  // Reach under the hood to get the actual DOM element that is
  // being used to render the component.
  var host = this._elementRef.nativeElement;
  // Here, we are going to walk up the DOM tree, checking to see
  // if we hit the "host" node. If we hit the host node at any
  // point, we know that the target must reside within the local
  // tree of the host.
  do {
    // If we hit the host node, we know that the target resides
    // within the host component.
    if ( current === host ) {
      return( true );
    }
    current = current.parentNode;
  } while ( current );
  // If we made it this far, we never encountered the host
  // component as we walked up the DOM tree. As such, we know that
  // the target resided outside of the host component.
  return( false );
}

  
}
//our root app component
import {Component} from '@angular/core'
import {DocClickDirective} from './docClickDirective'

@Component({
  selector: 'test-component',
  providers: [],
  template: `
    <div>
     <h3>{{name}}</h3>
      <div *ngIf="activateDirective"><div docClick (customClick)="clickHandler()">Directive Active</div></div>
    </div>
  `,
  directives: [DocClickDirective]
})


export class TestComponent {
  
  public _activateDirective:boolean = true;
  
  
  
  
  constructor() {
    this.name = "Test Component has the docClickDirective";
  }
  
 ngOnDestroy(){
    console.log('Destroyed Test Component');
  }
  
  get activateDirective():boolean{
    return this._activateDirective; 
  }
  set activateDirective(val:boolean){
    this._activateDirective = val;
  }
  
  clickHandler(){
    this.activateDirective = true;
  }
}
//our root app component
import {Component} from '@angular/core'


@Component({
  selector: 'demo-component',
  providers: [],
  template: `
    <div>
     <h3>{{name}}</h3>
    </div>
  `,
  directives: []
})


export class DemoComponent {
  
  
  constructor() {
    this.name = "Demo Component";
  }
  
 
}
//our root app component
import {Component} from '@angular/core'
import {RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS } from '@angular/router-deprecated'
import {PageOneComponent} from './PageOneComponent'
import {PageTwoComponent} from './PageTwoComponent'

@Component({
  selector: 'nested-routing-component',
  template: `
    <div>
      <h3>{{name}}</h3>
      <div>
      <a [routerLink]="['PageOne']">PageOne</a> | <a [routerLink]="['PageTwo']">PageTwo</a>
      
      </div>
      <router-outlet></router-outlet>
    </div>
  `,
  directives: [ROUTER_DIRECTIVES],
  
})

@RouteConfig([
   {
     path:'/pageOne',             
     name: 'PageOne',         
     component: PageOneComponent, 
     useAsDefault: true 
   },
  {
    path: '/pageTwo',
    name: 'PageTwo',
    component: PageTwoComponent
  }
])

export class NestedRoutingComponent {
  
  constructor() {
    this.name = 'Nested Routing Component';
  }
  
}
//our root app component
import {Component} from '@angular/core'
import {TestComponent} from './TestComponent'


@Component({
  selector: 'page-one-component',
  providers: [],
  template: `
    <div>
     <h4>{{name}}</h4>
     <test-component  *ngFor="let item of items;"></test-component>
      
    </div>
  `,
  directives: [TestComponent]
})


export class PageOneComponent {
  
  
  constructor() {
    this.name = "Page One Component has 3 components with a custom click event directive.";
    this.items = [
      {id:1},
      {id:2},
      {id:3}
      ];
  }
  
 
}
//our root app component
import {Component} from '@angular/core'


@Component({
  selector: 'page-two-component',
  providers: [],
  template: `
    <div>
     <h4>{{name}}</h4>
    </div>
  `,
  directives: []
})


export class PageTwoComponent {
  
  
  constructor() {
    this.name = "Page Two Component";
  }
  
 
}