krispo / angular-nvd3

AngularJS directive for NVD3 reusable charting library (based on D3). Easily customize your charts via JSON API.
http://krispo.github.io/angular-nvd3
MIT License
1.29k stars 377 forks source link

`a.map is not a function` error when trying to make NVD3 chart #591

Open chrismp opened 7 years ago

chrismp commented 7 years ago

I'm trying to make a chart with AngularJS and NVD3. But I keep getting an error.

Here's index.html:

<!DOCTYPE html>
<html>
<head>
    <style type="text/css">
        div.square {
            background-color: #ccc;
            height: 400px;
            width: 400px;
            margin: 10px;
        }
    </style>

    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.0-rc.2/angular.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.1/nv.d3.min.js"></script>
    <script src="https://rawgit.com/krispo/angular-nvd3/v1.0.4/dist/angular-nvd3.js"></script>
    <script src="app.js"></script>
</head>
<body ng-app="myApp" ng-controller="myCtrl">
  <div ng-repeat="item in items">
    <br>
    <form id="{{'customize-chart-' + item.number}}" novalidate>
        <textarea rows="5" cols="50" placeholder="Paste comma-separated data here." ng-model="textModel"></textarea>
        <br>
        <button id="{{'update-chart-' + item.number}}" ng-click="updateChart(item.number)">Update chart</button>
    </form>
  </div>
  <div ng-repeat="item in items">
    <div class="square">
        <nvd3 options="options" data="data" class="with-3d-shadow with-transitions"></nvd3>
    </div>
  </div>
</body>
</html>

Here's app.js"

var app=    angular.module("myApp",["nvd3"]);
app.controller("myCtrl",function($scope){
    $scope.items=   [
        {
            hed: '',
            subhed: '',
            number: chNum
        }
    ];

    $scope.textModel=   '';

    $scope.updateChart= function(passedItemNumber){
        var csvData=    d3.csv.parse(this.textModel);
        var headers=    d3.keys(csvData[0]);
        var nvd3Obj=    {};

        headers.forEach(function(d){
            nvd3Obj[d]= [];
        });

        csvData.forEach(function(d){
            for(var key in d){
                nvd3Obj[key].push(d[key]);
            }
        });

        $scope.options = {
            "chart": {
                "type": "lineChart",
                "height": 400,
                "margin": {
                    "top": 20,
                    "right": 20,
                    "bottom": 40,
                    "left": 55
                },
                "x": function(d) {
                    console.log(d);
                    return d[0];
                },
                "y": function(d) {
                    return d[1];
                },
                "useInteractiveGuideline": true,
                "dispatch": {},
                "xAxis": {
                    "axisLabel": "X axis"
                },
                "yAxis": {
                    "axisLabel": "Y axis"//,
                    // "axisLabelDistance": -10
                }
            }
        };

        $scope.data=    nvd3Obj;
    };
});

Here's what I paste into the textarea tag.

date,dow,sp500,nasdaq
1/1/16,10,15,8
1/3/16,5,3,7
1/5/16,12,18,12

When I paste that into the textarea, then click the "Update chart" button, this error appears in my browser's console.

angular.js:14290 TypeError: a.map is not a function
    at nv.d3.min.js:5
    at g (nv.d3.min.js:2)
    at update (nv.d3.min.js:2)
    at SVGSVGElement.<anonymous> (nv.d3.min.js:4)
    at d3.min.js:3
    at Y (d3.min.js:1)
    at Array._a.each (d3.min.js:3)
    at Array.b (nv.d3.min.js:4)
    at Array._a.call (d3.min.js:3)
    at Object.updateWithData (angular-nvd3.js:229)

The error does not refernce my script, app.js. What in my code causes this error? How do I fix it?

oksas commented 7 years ago

I had the same problem initially. It turned out to be the same issue listed here, which is that the data field you provide to nvd3 is expected to be an array (which has a map method), rather than an object (which does not have a map method). So I would try changing this line:

$scope.data=    nvd3Obj;

into

$scope.data = [nvd3Obj];
Manjunath-Siddappa commented 6 years ago

Thanks @oksas

Now it is working.

`//getting data here var dataObject = buildBOXChartData(data);

//Converting object to array dataObject = [dataObject];`