import { Component } from '@angular/core';
import { DataService } from './data.service';

@Component({
  selector: 'my-app',
  templateUrl: 'app/app.html'
})
export class AppComponent {
  data: IData[];
  newLabel: string;
  newValue: number;

  constructor(private dataService: DataService) { }

  ngOnInit() {
    this.dataService.$data.subscribe(data => {
      this.data = data;
    });
  }

  addData(): void {
    let newData = {
      label: this.newLabel,
      value: this.newValue
    } as IData;

    this.dataService.addData(newData);
  }
}


/*
Copyright 2017 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/
import { NgModule }      from '@angular/core';
import { FormsModule } from "@angular/forms";
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent }  from './app.component';
import { PieChartComponent }  from './pie-chart.component';
import { DataService }  from './data.service';

@NgModule({
  imports:      [ BrowserModule, FormsModule ],
  declarations: [ 
    AppComponent,
    PieChartComponent
  ],
  bootstrap:    [ AppComponent ],
  providers: [
    DataService
  ]
})
export class AppModule { }


/*
Copyright 2017 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';

platformBrowserDynamic().bootstrapModule(AppModule);


/*
Copyright 2017 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/
<!DOCTYPE html>
<html>
  <head>
    <title>Angular Quickstart</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link data-require="bootstrap-css" data-semver="4.0.0-alpha.4" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.4/css/bootstrap.min.css" />
    <link data-require="bootstrap@*" data-semver="4.0.5" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" />
    <style>
      body {color:#369;font-family: Arial,Helvetica,sans-serif;}
    </style>

    <!-- Polyfills -->
    <script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
    <script data-require="jquery" data-semver="3.1.1" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script src="https://npmcdn.com/tether@1.2.4/dist/js/tether.min.js"></script>
    <script data-require="bootstrap" data-semver="4.0.5" src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js"></script>
    
    <script src="https://unpkg.com/core-js/client/shim.min.js"></script>
    <script src="https://unpkg.com/zone.js@0.7.4?main=browser"></script>
    <script src="https://unpkg.com/systemjs@0.19.39/dist/system.src.js"></script>
    <script src="systemjs.config.js"></script>
    <script>
      System.import('main.js').catch(function(err){ console.error(err); });
    </script>
  </head>

  <body>
    <my-app>Loading AppComponent content here ...</my-app>
  </body>

</html>


<!-- 
Copyright 2017 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
-->
/**
 * WEB ANGULAR VERSION
 * (based on systemjs.config.js in angular.io)
 * System configuration for Angular samples
 * Adjust as necessary for your application needs.
 */
(function (global) {
  System.config({
    // DEMO ONLY! REAL CODE SHOULD NOT TRANSPILE IN THE BROWSER
    transpiler: 'ts',
    typescriptOptions: {
      // Copy of compiler options in standard tsconfig.json
      "target": "es5",
      "module": "system",
      "moduleResolution": "node",
      "sourceMap": true,
      "emitDecoratorMetadata": true,
      "experimentalDecorators": true,
      "lib": ["es2015", "dom"],
      "noImplicitAny": true,
      "suppressImplicitAnyIndexErrors": true
    },
    meta: {
      'typescript': {
        "exports": "ts"
      }
    },
    paths: {
      // paths serve as alias
      'npm:': 'https://unpkg.com/'
    },
    // map tells the System loader where to look for things
    map: {
      // our app is within the app folder
      app: 'app',

      // angular bundles
      '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
      '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
      '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
      '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
      '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
      '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
      '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
      '@angular/router/upgrade': 'npm:@angular/router/bundles/router-upgrade.umd.js',
      '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
      '@angular/upgrade': 'npm:@angular/upgrade/bundles/upgrade.umd.js',
      '@angular/upgrade/static': 'npm:@angular/upgrade/bundles/upgrade-static.umd.js',

      // other libraries
      'rxjs':                      'npm:rxjs@5.0.1',
      'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js',
      'ts':                        'npm:plugin-typescript@5.2.7/lib/plugin.js',
      'typescript':                'npm:typescript@2.0.10/lib/typescript.js',
      
      'd3':                      'https://d3js.org/d3.v3.min.js'

    },
    // 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'
      },
      'd3': {
         defaultExtension: "js"
      }
    }
  });

})(this);

/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/
<h1>Pie Chart with dynamic data</h1>
<div class="row">
    <div class="col-md-2">
        <div class="form-group">
            <label for="dataLabel">Label : </label>
            <input class="form-control" type="text" name="dataLabel" [(ngModel)]="newLabel" />    
        </div>
        <div class="form-group">
            <label for="dataValue">Value : </label>
            <input class="form-control" type="number" name="dataValue" [(ngModel)]="newValue" />
        </div>
        <button (click)="addData()" class="btn btn-primary">Add data</button>
    </div>
</div>
<div class="row">
    <div class="col-md-5" style="width:400px; height:400px;">
        <pie-chart></pie-chart>
    </div>
    <div class="col-md-7">
        <table class="table table-striped">
            <thead>
                <tr>
                    <td>Label</td>
                    <td>Value</td>
                </tr>
            </thead>
            <tbody>
                <tr *ngFor="let d of data">
                    <td [innerHTML]="d.label"></td>
                    <td [innerHTML]="d.value"></td>
                </tr>
            </tbody>
        </table>
    </div>
</div>
import { Component, ElementRef, ViewChild, AfterViewInit } from "@angular/core";
import { IData } from './data.interface';
import { DataService } from './data.service';
import * as D3 from "d3";

@Component({
    selector: "pie-chart",
    templateUrl: "app/pie-chart.html"
})

export class PieChartComponent implements AfterViewInit {
    @ViewChild("containerPieChart") element: ElementRef;

    private host: D3.Selection<any>;
    private svg: D3.Selection<any>;
    private width: number;
    private height: number;
    private radius: number;
    private htmlElement: HTMLElement;
    private pieData: IData[];

    constructor(private dataService: DataService) { }

    ngAfterViewInit() {
        this.htmlElement = this.element.nativeElement;
        this.host = D3.select(this.htmlElement);
        this.dataService.$data.subscribe(data => {
            this.pieData = data;
            this.setup();
            this.buildSVG();
            this.buildPie();
        });
    }

    private setup(): void {
        this.width = 250;
        this.height = 250;
        this.radius = Math.min(this.width, this.height) / 2;
    }

    private buildSVG(): void {
        this.host.html("");
        this.svg = this.host.append("svg")
            .attr("viewBox", `0 0 ${this.width} ${this.height}`)
            .append("g")
            .attr("transform", `translate(${this.width / 2},${this.height / 2})`);
    }

    private buildPie(): void {
        let pie = D3.layout.pie();
        let values = this.pieData.map(data => data.value);
        let arcSelection = this.svg.selectAll(".arc")
            .data(pie(values))
            .enter()
            .append("g")
            .attr("class", "arc");

        this.populatePie(arcSelection);
    }

    private populatePie(arcSelection: D3.Selection<D3.layout.pie.Arc<number>>): void {
        let innerRadius = this.radius - 50;
        let outerRadius = this.radius - 10;
        let pieColor = D3.scale.category20c();
        let arc = D3.svg.arc<D3.layout.pie.Arc<number>>()
            .outerRadius(outerRadius);
        arcSelection.append("path")
            .attr("d", arc)
            .attr("fill", (datum, index) => {
                return pieColor(this.pieData[index].label);
            });

        arcSelection.append("text")
            .attr("transform", (datum: any) => {
                datum.innerRadius = 0;
                datum.outerRadius = outerRadius;
                return "translate(" + arc.centroid(datum) + ")";
            })
            .text((datum, index) => this.pieData[index].label)
            .style("text-anchor", "middle");
    }
}
<div #containerPieChart></div>
import { Injectable } from "@angular/core";
import { BehaviorSubject } from "rxjs/BehaviorSubject";
import { IData } from './data.interface';

@Injectable()
export class DataService {
    private mockData: IData[] = [
      {
        label: "data1",
        value: 1,
      },
      {
        label: "data2",
        value: 2,
      },
      {
        label: "data3",
        value: 3,
      },
      {
        label: "data4",
        value: 4,
      }
    ];

    private dataSubject = new BehaviorSubject<IData[]>(this.mockData);
    
    $data = this.dataSubject.asObservable();

    addData(newData: IData) {
        this.mockData.push(newData);
        this.dataSubject.next(this.mockData);
    }
}
export interface IData {
    label: string,
    value: number
}