如何将REST响应返回到角JS标签来绘制D3 js饼图
问题描述:
本周我开始学习Angular Js和D3 Js。下面的代码可能是可悲的,但请耐心等待。如何将REST响应返回到角JS标签来绘制D3 js饼图
问题:我在尝试使用返回json {“chatjson”:“[10,20,30]”}的REST服务。 我想使用从REST收到的[10,20,30]绘制饼图。
代码覆盖:我正在使用ng控制器'validateCtrl'中的三个REST服务。两个服务运行正常,并显示所需的角度数据,但从第三个REST(请参阅函数'$ scope.getChartData')返回{“chatjson”:“[10,20,30]”},这是JSON,应该根据
圆角图代码中的响应显示饼图,这是我没有得到的。 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>
答
我认为主要的问题是,指令只运行他们的链接功能一次。发布在您的问题中的代码将执行链接函数中的所有绘图,该函数只能访问初始硬编码数据。
的解决方案,那么,是绘图代码从表单中的链接功能,你可以从一个观察者调用分离:
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
从你的问题返回示例对象,这似乎工作。
[代码形式](http://plnkr.co/edit/GBXJFozKqhZnK4Z46G2f?p=preview),对于任何感兴趣的人。 –
并[在这里工作](http://plnkr.co/edit/Zm9F9eJZIp5KjRySJAO6?p=preview)。现在写出答案。 –