<!DOCTYPE html>
<html>

<head>
    <title>Home Page</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<nav class="navbar navbar-inverse">
    <div class="container">
        <div class="navbar-header">
            <span class="navbar-brand">Just Components</span>
        </div>
        <div id="navbar">
            <ul class="nav navbar-nav">
                <li class="active"><a href="index.html">Home</a></li>
                <li><a href="items.html">Items</a></li>
                <li><a href="shapes.html">Shapes</a></li>
                <li><a href="items_and_shapes.html">Items and Shapes</a></li>
                <li><a href="other_static.html">Challenges/Consequences</a></li>
            </ul>
        </div>
    </div>
</nav>

<div class="container">
    <div>
        <h1>Angular 2 Components Without a SPA</h1>
        <table class="table table-bordered lead">
            <tr><td class="col-xs-3 text-right">Home</td><td>There is no angular on this page at all.</td></tr>
            <tr><td class="col-xs-3 text-right">Items</td><td>A static page with Component. Send data <em>OUT</em> of Component <em>TO</em> static page.</td></tr>
            <tr><td class="col-xs-3 text-right">Shapes</td><td>A static page with Component. Send data <em>INTO</em> Component <em>FROM</em> static page.</td></tr>
            <tr><td class="col-xs-3 text-right">Items & Shapes</td><td>Combine everything into one static page.</td></tr>
            <tr><td class="col-xs-3 text-right">Challenges/Consequences</td><td>for consideration, but not insurmountable</td></tr>
        </table>
    </div>
    <div>
        <h4>Why?</h4>
        <p>I'm asked routinely if you can put Angular 2 Components on a static page without creating a SPA.</p>
        <p>This is the answer: Yes</p>
        <h4>How?</h4>
        <p>This little app is an <em>imperfect</em> demonstration.</p>
        <p>Forget everything about @NgModel</p>
        <p>Forget everything about System.config path and app settings!</p>
        <p>Forget everything about tradtional Angular 2 bootstrapping!</p>
        <p>Each Component stands alone and boots itself</p>
    </div>

</div>
</body>
</html>
## A demonstration of using Angular 2 Components in a non-SPA static website
<!DOCTYPE html>
<html>

<head>
    <title>Static Pages with Angular 2 Components</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <script src="https://code.angularjs.org/2.0.0-beta.0/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="a2comps/config.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.0/Rx.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.0/angular2.min.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.0/http.min.js"></script>
    <script src="non_angular.js"></script>
    <script>
      System.import('a2comps/items.ts')
        .catch(console.error.bind(console));
    </script>
</head>

<body>
<nav class="navbar navbar-inverse">
    <div class="container">
        <div class="navbar-header">
            <span class="navbar-brand">Just Components</span>
        </div>
        <div id="navbar">
            <ul class="nav navbar-nav">
                <li><a href="index.html">Home</a></li>
                <li class="active"><a href="items.html">Items</a></li>
                <li><a href="shapes.html">Shapes</a></li>
                <li><a href="items_and_shapes.html">Items and Shapes</a></li>
                <li><a href="other_static.html">Challenges/Consequences</a></li>
            </ul>
        </div>
    </div>
</nav>

<div class="container">
    <div class="container">
        <div class="row">
            <div class="col-xs-8">
                <items>
                    <div class="text-center"><img src="gears.svg"></div>
                </items>
            </div>
            <div class="col-xs-4">
                <div class="panel panel-default">
                    <div class="panel-heading">
                        <h3 class="panel-title">Send Data OUT of a Component</h3>
                    </div>
                    <div class="panel-body">
                        <p>Click any row in a table. The row's data will be placed below.</p>
                        <br>
                        <p>The Angular Component generates a custom event. Plain old JS is used to listen for the custom event and update the view traditionally.</p>
                        <br>
                        <div id="itemizer"></div>
                    </div>
                </div>
            </div>

        </div>
    </div>
</div>
</body>

</html>
<!DOCTYPE html>
<html>

<head>
    <title>Static Pages with Angular 2 Components</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <script src="https://code.angularjs.org/2.0.0-beta.0/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="a2comps/config.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.0/Rx.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.0/angular2.min.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.0/http.min.js"></script>
    <script src="non_angular.js"></script>
    <script>
      System.import('a2comps/shapes.ts')
        .catch(console.error.bind(console));
      System.import('a2comps/items.ts')
        .catch(console.error.bind(console));
    </script>
</head>

<body>
<nav class="navbar navbar-inverse">
    <div class="container">
        <div class="navbar-header">
            <span class="navbar-brand">Just Components</span>
        </div>
        <div id="navbar">
            <ul class="nav navbar-nav">
                <li><a href="index.html">Home</a></li>
                <li><a href="items.html">Items</a></li>
                <li><a href="shapes.html">Shapes</a></li>
                <li class="active"><a href="items_and_shapes.html">Items and Shapes</a></li>
                <li><a href="other_static.html">Challenges/Consequences</a></li>
            </ul>
        </div>
    </div>
</nav>

<div class="container">
    <div class="container">
        <div class="row">
            <div class="col-xs-12">
                <div class="panel panel-default">
                    <div class="panel-body text-center">
                        Everything on one server-rendered non-spa page. See individual pages for details.
                    </div>
                </div>
            </div>
        </div>
        <div class="row">
            <div class="col-xs-6">
                <div class="panel panel-default">
                    <div class="panel-heading">
                        <h3 class="panel-title">Send Data OUT of a Component</h3>
                    </div>
                    <div class="panel-body">
                        <p>Click any row in a table. The row's data will be placed below.</p>
                        <br>
                        <p>The Angular Component generates a custom event. Plain old JS is used to listen for the custom event and update the view traditionally.</p>
                        <br>
                        <div id="itemizer"></div>
                    </div>
                </div>
            </div>
            <div class="col-xs-6">
                <div class="panel panel-default">
                    <div class="panel-heading">
                        <h3 class="panel-title">Send Data INTO a Component</h3>
                    </div>
                    <div class="panel-body">
                        <p>This button is outside any Angular Zone. When pressed, it fires a traditional JS custom event and sends new data to any listeners.</p>
                        <br>
                        <p>The Angular Component listens for the custom event and uses zone.run() to update the view.</p>
                        <br>
                        <button id="shapeShifter" class="btn btn-primary">Change the Shape List</button>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="row">
        <div class="col-xs-5">
            <items>
                <div class="text-center"><img src="gears.svg"></div>
            </items>
        </div>
        <div class="col-xs-6">
            <shapes>
                <div class="text-center"><img src="gears.svg"></div>
            </shapes>
        </div>
    </div>
</div>
</body>

</html>
<!DOCTYPE html>
<html>

<head>
    <title>Home Pages with Angular 2 Components</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <script src="https://code.angularjs.org/2.0.0-beta.0/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="a2comps/config.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.0/Rx.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.0/angular2.min.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.0/http.min.js"></script>
    <script src="non_angular.js"></script>
    <script>
      System.import('a2comps/shapes.ts')
        .catch(console.error.bind(console));
    </script>
</head>

<body>
<nav class="navbar navbar-inverse">
    <div class="container">
        <div class="navbar-header">
            <span class="navbar-brand">Just Components</span>
        </div>
        <div id="navbar">
            <ul class="nav navbar-nav">
                <li><a href="index.html">Home</a></li>
                <li><a href="items.html">Items</a></li>
                <li class="active"><a href="shapes.html">Shapes</a></li>
                <li><a href="items_and_shapes.html">Items and Shapes</a></li>
                <li><a href="other_static.html">Challenges/Consequences</a></li>
            </ul>
        </div>
    </div>
</nav>

<div class="container">
    <div class="container">
        <div class="row">
            <div class="col-xs-8">
                <shapes>
                    <div class="text-center"><img src="gears.svg"></div>
                </shapes>
            </div>
            <div class="col-xs-4">
                <div class="panel panel-default">
                    <div class="panel-heading">
                        <h3 class="panel-title">Send Data INTO a Component</h3>
                    </div>
                    <div class="panel-body">
                        <p>This button is outside any Angular Zone. When pressed, it fires a traditional JS custom event and sends new data to any listeners.</p>
                        <br>
                        <p>The Angular Component listens for the custom event and uses zone.run() to update the view.</p>
                        <br>
                        <button id="shapeShifter" class="btn btn-primary">Change the Shape List</button>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
</body>

</html>
<!DOCTYPE html>
<html>

<head>
    <title>Static Page</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<nav class="navbar navbar-inverse">
    <div class="container">
        <div class="navbar-header">
            <span class="navbar-brand">Just Components</span>
        </div>
        <div id="navbar">
            <ul class="nav navbar-nav">
                <li><a href="index.html">Home</a></li>
                <li><a href="items.html">Items</a></li>
                <li><a href="shapes.html">Shapes</a></li>
                <li><a href="items_and_shapes.html">Items and Shapes</a></li>
                <li class="active"><a href="other_static.html">Challenges/Consequences</a></li>
            </ul>
        </div>
    </div>
</nav>

<div class="container">
    <div class="starter-template">
        <h1 class="text-warning">The other non-angular static page</h1>
        <div class="lead">
            <h4>What is different from a SPA?</h4>
            <p>No router based Component lazy-loading</p>
            <p>No client side routing</p>
            <p>Uses traditional full round-trip requests for each page.</p>
            <h4>Challenges?</h4>
            <p >The browser window is reloaded from scratch on each navigation (No SPA).</p>
            <p>Navigating to a new page bootstraps a brand new angular app each time.</p>
            <h4>Consequences?</h4>
            <p>Data/state are not persisted between page changes.</p>
            <p>You will have to persist data/state in localStorage, IndexDB, server side, etc.</p>
            <p>Data/state management (moving data into and out of your components) is your responsibility.</p>
        </div>
    </div>

</div>
</body>
</html>
<?xml version="1.0" encoding="utf-8"?><svg width='188px' height='188px' xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid" class="uil-gears"><rect x="0" y="0" width="100" height="100" fill="none" class="bk"></rect><g transform="translate(-20,-20)"><path d="M79.9,52.6C80,51.8,80,50.9,80,50s0-1.8-0.1-2.6l-5.1-0.4c-0.3-2.4-0.9-4.6-1.8-6.7l4.2-2.9c-0.7-1.6-1.6-3.1-2.6-4.5 L70,35c-1.4-1.9-3.1-3.5-4.9-4.9l2.2-4.6c-1.4-1-2.9-1.9-4.5-2.6L59.8,27c-2.1-0.9-4.4-1.5-6.7-1.8l-0.4-5.1C51.8,20,50.9,20,50,20 s-1.8,0-2.6,0.1l-0.4,5.1c-2.4,0.3-4.6,0.9-6.7,1.8l-2.9-4.1c-1.6,0.7-3.1,1.6-4.5,2.6l2.1,4.6c-1.9,1.4-3.5,3.1-5,4.9l-4.5-2.1 c-1,1.4-1.9,2.9-2.6,4.5l4.1,2.9c-0.9,2.1-1.5,4.4-1.8,6.8l-5,0.4C20,48.2,20,49.1,20,50s0,1.8,0.1,2.6l5,0.4 c0.3,2.4,0.9,4.7,1.8,6.8l-4.1,2.9c0.7,1.6,1.6,3.1,2.6,4.5l4.5-2.1c1.4,1.9,3.1,3.5,5,4.9l-2.1,4.6c1.4,1,2.9,1.9,4.5,2.6l2.9-4.1 c2.1,0.9,4.4,1.5,6.7,1.8l0.4,5.1C48.2,80,49.1,80,50,80s1.8,0,2.6-0.1l0.4-5.1c2.3-0.3,4.6-0.9,6.7-1.8l2.9,4.2 c1.6-0.7,3.1-1.6,4.5-2.6L65,69.9c1.9-1.4,3.5-3,4.9-4.9l4.6,2.2c1-1.4,1.9-2.9,2.6-4.5L73,59.8c0.9-2.1,1.5-4.4,1.8-6.7L79.9,52.6 z M50,65c-8.3,0-15-6.7-15-15c0-8.3,6.7-15,15-15s15,6.7,15,15C65,58.3,58.3,65,50,65z" fill="#8f7f59"><animateTransform attributeName="transform" type="rotate" from="90 50 50" to="0 50 50" dur="1s" repeatCount="indefinite"></animateTransform></path></g><g transform="translate(20,20) rotate(15 50 50)"><path d="M79.9,52.6C80,51.8,80,50.9,80,50s0-1.8-0.1-2.6l-5.1-0.4c-0.3-2.4-0.9-4.6-1.8-6.7l4.2-2.9c-0.7-1.6-1.6-3.1-2.6-4.5 L70,35c-1.4-1.9-3.1-3.5-4.9-4.9l2.2-4.6c-1.4-1-2.9-1.9-4.5-2.6L59.8,27c-2.1-0.9-4.4-1.5-6.7-1.8l-0.4-5.1C51.8,20,50.9,20,50,20 s-1.8,0-2.6,0.1l-0.4,5.1c-2.4,0.3-4.6,0.9-6.7,1.8l-2.9-4.1c-1.6,0.7-3.1,1.6-4.5,2.6l2.1,4.6c-1.9,1.4-3.5,3.1-5,4.9l-4.5-2.1 c-1,1.4-1.9,2.9-2.6,4.5l4.1,2.9c-0.9,2.1-1.5,4.4-1.8,6.8l-5,0.4C20,48.2,20,49.1,20,50s0,1.8,0.1,2.6l5,0.4 c0.3,2.4,0.9,4.7,1.8,6.8l-4.1,2.9c0.7,1.6,1.6,3.1,2.6,4.5l4.5-2.1c1.4,1.9,3.1,3.5,5,4.9l-2.1,4.6c1.4,1,2.9,1.9,4.5,2.6l2.9-4.1 c2.1,0.9,4.4,1.5,6.7,1.8l0.4,5.1C48.2,80,49.1,80,50,80s1.8,0,2.6-0.1l0.4-5.1c2.3-0.3,4.6-0.9,6.7-1.8l2.9,4.2 c1.6-0.7,3.1-1.6,4.5-2.6L65,69.9c1.9-1.4,3.5-3,4.9-4.9l4.6,2.2c1-1.4,1.9-2.9,2.6-4.5L73,59.8c0.9-2.1,1.5-4.4,1.8-6.7L79.9,52.6 z M50,65c-8.3,0-15-6.7-15-15c0-8.3,6.7-15,15-15s15,6.7,15,15C65,58.3,58.3,65,50,65z" fill="#9f9fab"><animateTransform attributeName="transform" type="rotate" from="0 50 50" to="90 50 50" dur="1s" repeatCount="indefinite"></animateTransform></path></g></svg>
window.addEventListener('DOMContentLoaded', function () {
  let el = document.querySelector('#shapeShifter');
  if (el) {
    el.addEventListener('click', function () {
      window.dispatchEvent(new CustomEvent('shapeShifting', newShapes));
    });
  }
});

var newShapes = {
  detail: [
    {
      "shape": "This",
      "color": "Is",
      "area": 5,
      "label": "NEW"
    }
  ]
};

window.addEventListener('itemizing', function (e) {
  let el = document.querySelector('#itemizer');
  if (el) {
    let headers = Object.keys(e.detail);
    let innerHTML = '<table class="table"><thead><th>Property</th><th>Value</th></thead>';
    for(let i = 0; i < headers.length; i++){
      innerHTML += '<tr><td>'+headers[i]+'</td><td>'+e.detail[headers[i]]+'</td></tr>';
    }
    innerHTML += '</table>';
    el.innerHTML = innerHTML;
  }
});
  
System.config({
  //use typescript for compilation
  transpiler: "typescript",
  //typescript compiler options
  typescriptOptions: {
    emitDecoratorMetadata: true
  }
});
import {bootstrap, BROWSER_PROVIDERS, BROWSER_APP_PROVIDERS} from "angular2/platform/browser";
import {Component} from "angular2/core"
import {SimpleTable} from "./simple_table.ts"

@Component({
    selector: "items",
    template: `
    <simple-table [contentTitle]="contentTitle" [tableContent]="items"></simple-table>
  `,
    directives: [SimpleTable]
})

export class Items {
    contentTitle = "Items & Prices";
    items = ITEMS;
}
bootstrap(Items);


//========================
// MOCK DATA
const ITEMS: Item[] = [
    {
    "id": 0,
    "name": "Item 0",
    "price": "$0"
},
    {
        "id": 1,
        "name": "Item 1",
        "price": "$1"
    },
    {
        "id": 2,
        "name": "Item 2",
        "price": "$2"
    },
    {
        "id": 3,
        "name": "Item 3",
        "price": "$3"
    },
    {
        "id": 4,
        "name": "Item 4",
        "price": "$4"
    },
    {
        "id": 5,
        "name": "Item 5",
        "price": "$5"
    }
];

import {bootstrap, BROWSER_PROVIDERS, BROWSER_APP_PROVIDERS} from "angular2/platform/browser";
import {Component, NgZone, enableProdMode} from "angular2/core"
import {SimpleTable} from "./simple_table.ts"
//enableProdMode();

@Component({
  selector: "shapes",
  providers: [],
  template: `
    <simple-table [contentTitle]="contentTitle" [tableContent]="shapes"></simple-table>
  `,
  directives: [SimpleTable]
})
export class Shapes {
    contentTitle = "Shapes";
    shapes = SHAPES;

    constructor(zone:NgZone){
        window.addEventListener('shapeShifting', (e) =>{
            zone.run(() => { this.shapes = e.detail; });
        })
    }
}

bootstrap(Shapes);

//========================
//MOCK DATA
const SHAPES:Shape[] = [
  {
    "shape": "triangle",
    "color": "red",
    "area": 5,
    "label": "T1"
  },
  {
    "shape": "triangle",
    "color": "green",
    "area": 27,
    "label": "T2"
  },
  {
    "shape": "triangle",
    "color": "yellow",
    "area": 15,
    "label": "T3"
  },
  {
    "shape": "triangle",
    "color": "red",
    "area": 10,
    "label": "T4"
  },
  {
    "shape": "quadrangle",
    "color": "red",
    "area": 25,
    "label": "Q1"
  },
  {
    "shape": "quadrangle",
    "color": "red",
    "area": 44,
    "label": "Q2"
  },
  {
    "shape": "circle",
    "color": "red",
    "area": 44,
    "label": "Q2"
  },
  {
    "shape": "circle",
    "color": "black",
    "area": 44,
    "label": "Q2"
  }
];
import {Component, Input} from "angular2/core"

@Component({
    selector: "simple-table",
    template: `
    <h6 class="pull-right">Custom Reusable Component</h6>
    <div class="clearfix"></div>
    <div class="well">
      <h4>{{contentTitle}}</h4>
    </div>
        <table class="table table-hover">
            <thead>
            <tr>
                <th *ngFor="#header of headers">{{header | uppercase}}</th>
            </tr>
            </thead>
            <tbody (click)="sendRowData($event)">
            <tr *ngFor="#row of tableContent">
                <td *ngFor="#header of headers">{{row[header]}}</td>
            </tr>
            </tbody>
        </table>
  `,
    directives: []
})
export class SimpleTable {
    private headers;
    @Input("contentTitle") contentTitle;
    @Input("tableContent") tableContent;

    ngOnInit() {
        this.headers = Object.keys(this.tableContent[0]);
    }

    sendRowData(el) {
        let selected = el.target.parentElement;
        this.changeRowSelection(selected);
        let row = {detail : this.getRowData(selected)};
        window.dispatchEvent(new CustomEvent('itemizing', row));
    }

    changeRowSelection(selected) {
        let trs = document.querySelectorAll('tr');
        for (let i = 0; i < trs.length; i++) {
            trs[i].classList.remove('active');
        }
        selected.classList.add('active');
    }

    getRowData(selected) {
        let rowData = {};
        let tds = selected.children;
        for (let i = 0; i < tds.length; i++) {
            rowData[this.headers[i]] = tds[i].textContent;
        }
        return rowData;
    }
}