Search code examples
angularjsd3.jsangularjs-scoped3plus

I am trying to inject a partial template in Angular that contains a graph


I am creating an Angular application in ASP.NET with partial templates. When I select the menu, and click "Employees", a controller calls a webservice and returns the correct JSON data, and I store it in $scope.message. I've displayed $scope.message on the screen, and everything works.

However, I want to feed $scope.message as data source to a D3plus boxplot graph stored in a partial template called employees.html. It does not seem to be working. Perhaps I am making an obvious mistake and would greatly appreciate the community's help. Thank you! Here is mu code:

Webform1.aspx (webform):

...
<body onload="loadPikaday()" data-ng-app="Demo">

    <%-- Header --%>
    <div id="topBanner" class="topBanner">
        <div id="menu" class="menu">
            Report from: &emsp; 
            <input id="startDate" size="6" type="text" data-ng-model="startDate" /> &emsp; To &emsp; 
            <input id="endDate" size="6" type="text" data-ng-model="endDate" />&emsp; 

           <%-- Dropdown menu --%>
            <div class="dropdown">
            <button onclick="myFunction()" class="dropbtn">MENU</button>
                <div id="myDropdown" class="dropdown-content">
                    <a href="#/cases">Cases</a>
                    <a href="#/protocols">Protocols</a>
                    <a href="#/employees">Employees</a>
                </div>
            </div>
        </div>
</div>


    <%-- Where html is injected--%>
    <div data-ng-view=""></div>

</body>
...

myScript.js (Angular module):

/// <reference path="angular.min.js" />

var app = angular.module("Demo", ['ngRoute'])
                 .config(function ($routeProvider) {
                     $routeProvider
                         .when('/cases', { // Root: initialize with cases
                             templateUrl: 'templates/cases.html',
                             controller: 'casesController'
                         })
                         .when('/protocols', { // Root: initialize with cases
                             templateUrl: 'templates/protocols.html',
                             controller: 'protocolsController'
                         })
                         .when('/employees', {
                             templateUrl: 'templates/employees.html',
                             controller: 'employeesController'
                         })
                 })
                .controller('casesController', function ($scope) {
                    $scope.message = "Cases!";
                })
                .controller('protocolsController', function ($scope) {
                    $scope.message = "This is the protocols page!";
                })
                .controller('employeesController', function ($scope, $http) {
                    $http.get('dataWebService.asmx/getTotalForDateIntervalEmployees', {
                        params: { startDate: '2015-01-01', endDate: '2016-08-01' }
                    })
                    .then(function (response) {
                        $scope.message = response.data;
                    })
                });

employees.html (injected partial template):

<!doctype html>
<meta charset="utf-8">

<script src="//d3plus.org/js/d3.js"></script>
<script src="//d3plus.org/js/d3plus.js"></script>

<div id="viz"></div>

<script>

  var data = {{message}};

  var visualization = d3plus.viz()
   .container("#viz")
   .data(data)
   .type("box")
   .id("name")
   .x("building")
   .y("total")
   .time(false)
   .ui([{
       "label": "Visualization Type",
       "method": "type",
       "value": ["scatter", "box"]
   }])
   .draw()

</script>

Solution

  • Here is a simple example using a directive...

    var app = angular.module('app', []);
    
    app.controller('AppCtrl', function($scope, $http) {
    
        $scope.data = [];
    
        $http.get('/data').then(function(data) {
            $scope.data = data.data;
        });
    });
    
    app.directive('chart', function() {
        return {
            restrict: 'EA',
            scope: {
                data: '=',
            },
            link: function(scope, elem, atts) {
    
                var svg = d3.select(elem[0]).append('svg'),
                    chart = svg.append('g');
    
                scope.$watch('data', function(data) {
                    chart.selectAll('*').remove();
    
                    if (data.length) {
                        updateChartData(data);
                    }
                });
    
                function updateChartData(data) {
                    // add all your d3 code here...
                }
            }
        };
    });
    

    Then you can bind the data with something like

    <chart data="data"></chart>