<html>
  <head>
    <title>Angular 2 grid</title>
 
    <!-- 1. Load libraries -->
    <!-- IE required polyfills, in this exact order -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.33.3/es6-shim.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.20/system-polyfills.js"></script>
 
    <script src="https://code.angularjs.org/2.0.0-beta.6/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="https://code.angularjs.org/2.0.0-beta.6/Rx.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.6/angular2.dev.js"></script>
 
    <!-- 2. Configure SystemJS -->
    <script>
      System.config({
        transpiler: 'typescript',
        typescriptOptions: { emitDecoratorMetadata: true }
      });
      System.import('app.ts')
            .then(null, console.error.bind(console));
    </script>
  </head>
  <body>
    <app>Loading</app>
  </body>
</html>
import {Component} from 'angular2/core';
import {bootstrap} from 'angular2/platform/browser';
import {NgFor} from 'angular2/common';
import {enableProdMode} from 'angular2/core';
 
enableProdMode();
 
@Component({
    selector: 'app',
    template: `
        <table>
            <tr *ngFor="#row of grid">
                <td *ngFor="#name of row">
                    {{name}}
                </td>
            </tr>
        </table>
    `,
    directives: [NgFor]
})
export class AppCmp {
    private grid: any;
    private gridWidth = 30;
    private gridHeight = 500;
    private interval = 2000;
    private changePerInterval = 10000;
    private names = ['Joe', 'Michael', 'David', 'Jones', 'Phil', 'Johnson', 'Janes', 'Anna', 'Hugo', 'Lina', 'Scotte', 'Nam', 'Tran',
                                    'Bill', 'Mark', 'Rihanna', 'Justin', 'Bieber', 'James', 'Cameron', 'Peter', 'Anderson', 'Ronaldo', 'Scholes', 'Giggs',
                                    'Lee', 'Cedric', 'Young', 'Zim', 'Hue', 'Zac', 'Jonas', 'Miley', 'Thomas', 'September', 'Green', 'Red', 'Rose', 'Pink'];
 
    constructor() {
        this.grid = this.initializeGrid();
        this.beginDataChanges();
    }
 
    initializeGrid() {
        var grid = [];
        for (var row = 0; row < this.gridHeight; row++) {
            grid[row] = [];
            for (var column = 0; column < this.gridWidth; column++) {
                grid[row].push(this.getRandomName());
            }
        }
        return grid;
    }
 
    getRandomNumber(maxBound) {
        return Math.floor(Math.random() * maxBound);
    }
 
    getRandomName() {
        var i = this.getRandomNumber(this.names.length);
        return this.names[i];
    }
 
    beginDataChanges() {
        setInterval(() => {
            for (var i = 0; i < this.changePerInterval; i++) {
                var randomRow = this.getRandomNumber(this.gridHeight);
                var randomColumn = this.getRandomNumber(this.gridWidth);
                var name = this.getRandomName();
                this.grid[randomRow][randomColumn] = name;
            }
        }, this.interval);
    }
    
    customTrackBy(index: number, obj: any): any {
        return index;
    }
}
 
bootstrap(AppCmp);