angular-nvd3 を使用したユーザーの選択に応じて、Web アプリで動的にグラフを生成しようとしています。ユーザーがオプションを選択したときに、d3.selection.append を使用してグラフのコンテナーを作成する関数があります。
"charts.html" の静的チャート コンテナーのコメントを外すと、データが正常に読み込まれるようです。ただし、ユーザーが選択すると、グラフのない空白のグラフ コンテナーが表示されます。
charts.html
<div ng-controller="chartsCtrl">
<form class="dropdown-search">
<div>
<label>Select level: </label>
<br>
<select ng-model="child.levelSelect">
<option ng-repeat="levelName in child.levelNames" value="{{levelName}}">
{{levelName}}
</option>
</select>
<br>
</div>
<div>
<label>Select group: </label>
<br>
<select ng-model="child.groupSelect">
<option ng-repeat="groupName in child.groupNames" value="{{groupName}}">
{{groupName}}
</option>
</select>
<br>
</div>
<div>
<label>Select chart: </label>
<br>
<select ng-model="child.headerSelect">
<option ng-repeat="header in child.headers" value="{{header}}">
{{header}}
</option>
</select>
<br>
</div>
</form>
<div id="myCharts"></div>
<!--<div class="panel">-->
<!--<div class="panel-heading">-->
<!--<h3 class="panel-title">-->
<!--Line and Bar Graphs-->
<!--<span class="panel-options">-->
<!--<a href="#" class="panel-refresh">-->
<!--<i class="icon ti-reload"></i>-->
<!--</a>-->
<!--<a href="#" class="panel-minimize">-->
<!--<i class="icon ti-angle-up"></i>-->
<!--</a>-->
<!--<a href="#" class="panel-close">-->
<!--<i class="icon ti-close"></i>-->
<!--</a>-->
<!--</span>-->
<!--</h3>-->
<!--</div>-->
<!--<div class="panel-body">-->
<!--<div class='with-3d-shadow with-transitions'>-->
<!--<nvd3 options="myOptions" data="myData"></nvd3>-->
<!--</div>-->
<!--</div>-->
<!--</div>-->
</div>
chartsCtrl.js
var myApp = angular.module('webapp', ['nvd3']);
myApp.controller("chartsCtrl", ['$scope', 'ProdFactory', function ($scope, ProdFactory){
var parentScope = $scope.$parent;
parentScope.child = $scope;
parentScope.dropdown = true;
var onLevelNamesComplete = function(data){
$scope.levelNames = data;
};
var onGroupNamesComplete = function(data){
$scope.groupNames = data;
};
var onGroupDataComplete = function(data){
$scope.groupData = data;
$scope.headers = data[0].splice(3,data.length-3);
};
var onChartDataComplete = function(data){
$scope.chartData = data;
$scope.processedData = ProdFactory.processChartData(
$scope.chartData, $scope.headerSelect);
$scope.myData = $scope.processedData.map(function(series) {
series.values = series.values.map(function(d) { return {x: d[0], y: d[1] } });
return series;
});
};
ProdFactory.getLevelNames().then(onLevelNamesComplete);
$scope.$watch('levelSelect', function(){
ProdFactory.getGroupNames($scope.levelSelect)
.then(onGroupNamesComplete);
});
$scope.$watch('groupSelect', function(){
if($scope.groupSelect != null){
ProdFactory.getGroupData($scope.groupSelect)
.then(onGroupDataComplete);
ProdFactory.chartSegment("test");
}
});
$scope.$watch('headerSelect', function(){
if($scope.groupSelect != null
&& $scope.headerSelect != null){
ProdFactory.chartSegment($scope.headerSelect);
ProdFactory
.getChartData($scope.groupSelect,$scope.headerSelect)
.then(onChartDataComplete);}
});
$scope.levelSelect = null;
$scope.groupSelect = null;
$scope.headerSelect = null;
$scope.myOptions = {
chart: {
type: 'linePlusBarChart',
margin: {
top: 30,
right: 60,
bottom: 50,
left: 70
},
bars: {
forceY: [0]
},
bars2: {
forceY: [0]
},
color: ['#2ca02c', 'darkred'],
x: function(d,i) { return i },
xAxis: {
axisLabel: 'X Axis',
showMaxMin: true,
tickFormat: function(d) {
var dx = $scope.myData[0].values[d] && $scope.myData[0].values[d].x || 0;
return d3.time.format('%x')(new Date(dx));
}
},
x2Axis: {
tickFormat: function(d) {
var dx = $scope.myData[0].values[d] && $scope.myData[0].values[d].x || 0;
return d3.time.format('%b-%Y')(new Date(dx))
},
showMaxMin: false
},
y1Axis: {
axisLabel: 'Y1 Axis',
tickFormat: function(d){
return d3.format(',f')(d);
},
axisLabelDistance: 12
},
y2Axis: {
axisLabel: 'Y2 Axis',
tickFormat: function(d) {
return '$' + d3.format(',.2f')(d)
}
},
y3Axis: {
tickFormat: function(d){
return d3.format(',f')(d);
}
},
y4Axis: {
tickFormat: function(d) {
return '$' + d3.format(',.2f')(d)
}
}
}
};
}])
ProdFactory.js
var myApp = angular.module('webapp');
myApp.factory("ProdFactory", ['$http',function($http){
var getData = function(){
return $http.get('<some url>')
.then(function(response){
return response.data;
});
};
var getLevelNames = function(){
return this.getData()
.then(function(data){
var allTextLines = data.split(/\r\n|\n/);
var levelNames = [];
for(i=1; i<allTextLines.length-1; i++){
var element = allTextLines[i].split(',');
var levelColumn = element[0];
if(levelNames.indexOf(levelColumn)<0){
levelNames.push(levelColumn);
};
};
//console.log(levelNames);
return levelNames;
});
};
var getGroupNames = function(levelName){
return this.getData()
.then(function(data){
var allTextLines = data.split(/\r\n|\n/);
var groupNames = [];
for(i=1; i<allTextLines.length-1; i++){
var element = allTextLines[i].split(',');
if(element[0] == levelName &&
groupNames.indexOf(element[1])<0){
groupNames.push(element[1]);
};
};
//console.log(groupNames);
return groupNames;
});
};
var getGroupData = function(groupName){
return this.getData()
.then(function(data){
var allTextLines = data.split(/\r\n|\n/);
var groupData = [];
if(groupName !== null){
groupData = [allTextLines[0].split(',')];
}
//else{return null;}
for(i = 1; i<allTextLines.length-1; i++){
var element = allTextLines[i].split(',');
if(element[1] == groupName){
groupData.push(element);
};
};
//console.log(groupData);
return groupData;
});
};
var getChartData = function(groupName, headerName){
return this.getGroupData(groupName)
.then(function(data){
var n = data[0].indexOf(headerName);
var chartData = [];
for(i = 1; i<data.length; i++){
var row = [data[i][2],data[i][n]].map(Number);
chartData.push(row);
};
//console.log(chartData);
return chartData;
});
};
var processChartData = function(data, headerName){
var chartData = [];
var changeData = getChange(data);
chartData.push({
key: headerName,
bar: true,
values: data
});
chartData.push({
key: headerName + " change",
values: changeData
});
console.log(chartData);
return chartData;
};
var getChange = function(data){return data};
function chartSegment(tableName){
var mainBody = d3.select("#myCharts");
var panelMain = mainBody.append('div').classed("panel", true);
var panelHeading = panelMain.append('div').classed("panel-heading", true);
var panelTitle = panelHeading.append('h3').classed("panel-title", true);
var panelTitleText = panelTitle.text(tableName);
var panelOptions = panelTitle.append('span').classed("panel-options",true);
var panelRefresh = panelOptions.append('a')
.attr("href", '#').classed("panel-refresh",true);
var panelRefreshIcon = panelRefresh.append('i').classed("icon ti-reload", true);
var panelMin = panelOptions.append('a')
.attr("href", '#').classed("panel-minimize",true);
var panelMinIcon = panelMin.append('i').classed("icon ti-angle-up", true);
var panelClose = panelOptions.append('a')
.attr("href", '#').classed("panel-close",true);
var panelCloseIcon = panelClose.append('i').classed("icon ti-close", true);
var panelBody = panelMain.append('div').classed("panel-body", true);
var panelChart = panelBody.append('div').attr("id", tableName)
.classed("with-3d-shadow with-transitions", true);
var chartElement = panelChart.append('nvd3').attr("options", "myOptions")
.attr("data","myData");
};
return {
getLevelNames: getLevelNames,
getGroupNames: getGroupNames,
getGroupData: getGroupData,
getChartData: getChartData,
processChartData: processChartData,
chartSegment: chartSegment
};
}]);