如何将REST响应放回angular JS标签中绘制D3 js饼图

How to put REST response back in angular JS tag to draw D3 js pie chart

我这周开始学习 Angular Js 和 D3 Js。下面的代码可能很可怜,但请多多包涵。

问题: 我正在尝试使用 returns json {"chatjson":"[10,20,30] 的 REST 服务]”}。 我想使用从 REST 接收到的 [10,20,30] 绘制一个饼图。

代码概述: 我在 ng-controller 'validateCtrl' 中使用了三个 REST 服务。两项服务 运行 正常并在 angular 中显示所需数据,但来自第三个 REST(请参阅函数 '$scope.getChartData' ) returns {"chatjson":" [10,20,30]"} ,即 JSON ,应显示基于
处的响应的饼图 angular 代码中的圆环图标记,我没有得到。 D3 Js代码写在底部。 D3 代码适用于硬编码数据。

实际代码

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
<html>

<head>
<script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="http://d3js.org/d3.v3.min.js"></script>
</head>



<body>
<h2>Angular Example</h2>

<form ng-app="myApp" ng-controller="validateCtrl" 
name="myForm" novalidate>

<p>Username:<br>
<input type="text" name="user" ng-model="user" required>
<span style="color:red" ng-show="myForm.user.$dirty && myForm.user.$invalid">
<span ng-show="myForm.user.$error.required">Username is required.</span>
</span>
</p>

<p>country:<br>
<input type="text" name="country" ng-model="country" required>
<span style="color:red" ng-show="myForm.country.$dirty && myForm.country.$invalid">
<span ng-show="myForm.country.$error.required">country is required.</span>

</span>
</p>

<p>
<input type="submit" value="save" ng-click="send()"
ng-disabled="myForm.user.$dirty && myForm.user.$invalid ||  
myForm.country.$dirty && myForm.country.$invalid">
</p>

<ul>
  <li ng-repeat="y in detail">
    {{ y.name + ', ' + y.country }}
  </li>
</ul>

<input type="submit" value="Get Country List" ng-click="getData()">
<input type="submit" value="Get Pie Chart" ng-click="getChartData()">

<ul>
  <li ng-repeat="x in names">
    {{ x.name + ', ' + x.country }}
  </li>
</ul>

<div>
<donut-chart data="chartData"></donut-chart>
</div>
</form>

<script>
var app = angular.module('myApp', []);
app.controller('validateCtrl', function($scope,$http) {



    $scope.chartData=[12,13,60]; // Hard coded for testing purpose
    $scope.user = 'Anukul';
    $scope.country = 'India';
//=============== REST  for fetching data from DB for Table details ==============
    $scope.getData = function(){
    var getApi="http://localhost:9080/nextapp/person/getList";

    $http.get(getApi).success(function(response){$scope.names=response.records;
    });
    };
//=============== REST  for fetching data for drawing chart ==============
    $scope.getChartData = function(){
    var getchartApi="http://localhost:9080/nextapp/person/getChart";

    $http.get(getchartApi).success(function(response){$scope.chartData=response;
    });
    };
//=============== REST for inserting data in DB ==============
    $scope.send = function(){
    var name = $scope.user;
    var country = $scope.country;
    var api="http://localhost:9080/nextapp/person/"+name+"/"+country;
    $http.get(api)
    .success(function(response) {$scope.detail = response.result;});
};
//========== End of REST  ==============================
});


//===================== new add for D3 Pie chart ============

    app.directive('donutChart',function(){
    function link(scope,el){
    //---- D3 code goes here
    var data = scope.data;
    var color = d3.scale.category10()
    var el = el[0]
    var width = 500
    var height = 500
    var min = Math.min(width,height)


    var pie = d3.layout.pie().sort(null)
    var arc = d3.svg.arc()
                .outerRadius(125)
                .innerRadius(75)

    var group = d3.select(el).append('svg')
        .attr({width:width,height:height})
        .append('g')
            .attr('transform','translate('+width/2+','+height/2+')')

    var arcs = group.selectAll(".arc")
                .data(pie(data))
                .enter()
                .append('g')
                .attr("class","arc")
    arcs.append("path")
        .attr("d",arc)
        .attr("fill",function(d){return color(d.data);});

    arcs.append("text")
        .attr("transform",function(d){return "translate (" + arc.centroid(d)+")";})
        .text(function(d){return d.data;});



    //d3.select(el[0]).append('svg')
    }

    return{
    link: link,
    restrict:'E',
    scope:{data:'='}
    }
    }
    )




</script>

</body>
</html>

我认为主要问题是指令仅 运行 它们的 link 函数一次。您问题中发布的代码完成了 link 函数中的所有绘图,该函数只能访问初始硬编码数据。

然后,解决方案是将绘图代码与 link 函数分开,以一种您可以从观察者调用的形式:

app.directive('donutChart',function(){
    function link(scope,element){
      scope.el = element[0]; // Cache a reference to the element
      draw(scope.data, scope.el); // Initial draw
    }

    function draw(data, el) {
      var color = d3.scale.category10(),
          width = 500,
          height = 500,
          min = Math.min(width,height),


          pie = d3.layout.pie().sort(null),
          arc = d3.svg.arc()
                  .outerRadius(125)
                  .innerRadius(75);

      d3.select("svg").remove(); // Clear old pie chart

      var group = d3.select(el).append('svg')
            .attr({width:width,height:height})
            .append('g')
            .attr('transform','translate('+width/2+','+height/2+')'),

          arcs = group.selectAll(".arc")
            .data(pie(data))
            .enter()
            .append('g')
            .attr("class","arc");

      arcs.append("path")
          .attr("d",arc)
          .attr("fill",function(d){return color(d.data);});

      arcs.append("text")
          .attr("transform",function(d){return "translate (" + arc.centroid(d)+")";})
          .text(function(d){return d.data;});
    }

    return{
      link: link,
      restrict:'E',
      scope:{data:'='},
      // Add a controller here to $watch for data changes
      controller: function($scope) {
        $scope.$watch('data', function(newData) {
          draw(newData, $scope.el); // Re-draw the chart
        });
      }
    };
  });

我注意到的另一件事可能不是实际问题,因为它取决于实际的服务器响应。设置图表数据时,您可以这样做:

$scope.chartData = response;

但是,根据您问题的内容,预期的回复如下:

{ "chartjson": [10, 20, 30] }

如果是这样,您的测试图表数据只是一个数组,如下所示:

$scope.chartData = [12, 13, 60];

然后我希望从这样的响应中获取数组:

$scope.chartData = response.chartjson;

您可以看到 in this plunker 我模拟了 $httpBackend 到 return 您问题中的示例对象,这似乎有效。