0

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
    };
    }]);
4

1 に答える 1

0

別のアプローチが機能するようです....もっと良い方法があるかどうか疑問に思っています

d3selection を使用してチャートを追加する代わりに、ng-repeat を使用しています。

charts.html

<div ng-repeat="data in myData">
<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'>
            <!--<svg id="sian"> </svg>-->
            <nvd3 options="myOptions" data="data"></nvd3>
        </div>
    </div>
</div>
</div>

コントローラ

var $scope.myData = [];

var onChartDataComplete = function(data){
        $scope.chartData = data;

        $scope.processedData = ProdFactory.processChartData(
            $scope.chartData, $scope.headerSelect);
        $scope.myData.push($scope.processedData.map(function(series) {
                    series.values = series.values.map(function(d) { return {x: d[0], y: d[1] } });
                    return series;
                }));

    };
于 2016-07-02T07:49:51.020 に答える