0

In Amcharts Stock chart, I am trying to show data, i'm getting this data in json form from the database. The error it is showing, "Uncaught TypeError: dp[ds.categoryField].setFullYear is not a function at Object.AmCharts.baseYearInitialize". JSON array is fine, and also if i keep only one dataset, then it works fine, as soon as i enter a year, whose data i have already in json form, it shows me an error.

var chart;
var SER = [];
//var SER;

first();

function first() {
    for (var i = 0; i < 5; i++) {
        generateChartData(2000 + i);
    }
    //SER = JSON.stringify(SER1);
    //console.log(SER1);
    dd();
}

function generateChartData(year) {
    var firstDate = new Date(year, 0, 1);
    var temp = [];
    for (var i = 0; i < 365; i++) {
        var newDate = new Date(firstDate);
        newDate.setDate(newDate.getDate() + i);
        newDate = ((newDate.getMonth() + 1) < 10 ? "0" + (newDate.getMonth() + 1) : (newDate.getMonth() + 1)) +
            "-" + (newDate.getDate() < 10 ? "0" + newDate.getDate() : newDate.getDate()) +
            "-" + year;
        temp.push({
            date: newDate,
            value: Math.round(Math.random() * (40 + i)) + 100 + i
        });
    }
    SER.push(temp);
}

function dd() {
    AmCharts.addInitHandler(function(chart) {
        AmCharts.baseYearInitialize = function(chart) {
            for (var x = 0; x < chart.dataSets.length; x++) {
                var ds = chart.dataSets[x];
                if (ds.baseYear !== undefined) {
                    for (var i = 0; i < ds.dataProvider.length; i++) {
                        var dp = ds.dataProvider[i];  dp[ds.categoryField].setFullYear(ds.baseYear);
                    }
                }
            }
        }
        AmCharts.baseYearInitialize(chart);
    }, ["stock"]);
    
    chart = AmCharts.makeChart("chartdiv", {
        "type": "stock",
        "theme": "light",
        "dataSets": [{
            "title": "2000",
            "fieldMappings": [{
                "fromField": "value",
                "toField": "value"
            }],
            "dataProvider": SER[0],
            "categoryField": "date"
        }
        /* keeping more than one dataset showing error
        , {
            "title": "2001",
            "fieldMappings": [{
                "fromField": "value",
                "toField": "value"
            }],
            "dataProvider": SER[1],
            "categoryField": "date",
            "compared": true,
            "baseYear": 2000
        }, {
            "title": "2002",
            "fieldMappings": [{
                "fromField": "value",
                "toField": "value"
            }
        */
        ],
        "panels": [{
            "title": "Value",
            "categoryAxis": {},
          	"dateFormats": 'DD-MM-YYYY',
            "stockGraphs": [{
                "id": "g1",
                "valueField": "value",
                "lineThickness": 2,
                "comparable": true,
                "compareField": "value",
                "balloonText": "[[title]]:<b>[[value]]</b>",
                "compareGraphBalloonText": "[[title]]:<b>[[value]]</b>",
                "compareGraph": {
                    "dashLength": 5,
                    "lineThickness": 2
                }
            }],
            "stockLegend": {
                "periodValueTextComparing": "[[percents.value.close]]%",
                "periodValueTextRegular": "[[value.close]]"
            }
        }],
        "panelsSettings": {
            "recalculateToPercents": "never"
        },
        "chartScrollbarSettings": {
            "graph": "g1"
        },
        "chartCursorSettings": {
            "valueBalloonsEnabled": true,
            "fullWidth": true,
            "cursorAlpha": 0.1,
            "valueLineBalloonEnabled": true,
            "valueLineEnabled": true,
            "valueLineAlpha": 0.5
        },
        "periodSelector": {
            "position": "bottom",
            "periods": [{
                "period": "MM",
                "selected": true,
                "count": 1,
                "label": "1 month"
            }, {
                "period": "YYYY",
                "count": 1,
                "label": "1 year"
            }, {
                "period": "YTD",
                "label": "YTD"
            }, {
                "period": "MAX",
                "label": "MAX"
            }]
        }

    });
    $('document').ready(function() {
        $('#submit').on('click', function() {
            add(document.getElementById('year').value);
        });
    });
}

function add(yr) {
    chart.dataSets.push({
        "title": yr,
        "fieldMappings": [{
            "fromField": "value",
            "toField": "value"
        }],
        "dataProvider": SER[yr-2000],
        "categoryField": "date",
        "compared": true,
        "baseYear": 2000
    });
    AmCharts.baseYearInitialize(chart);
    chart.validateData();
}
#chartdiv {
                width: 100%;
                height: 500px;
                font-family: Verdana;
                font-size: 12px;
            }
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
        <script type="text/javascript" src="https://www.amcharts.com/lib/3/amcharts.js"></script>
        <script type="text/javascript" src="https://www.amcharts.com/lib/3/serial.js"></script>
        <script type="text/javascript" src="https://www.amcharts.com/lib/3/themes/light.js"></script>
        <script type="text/javascript" src="https://www.amcharts.com/lib/3/amstock.js"></script>
        <input type="text" id="year"><input type="submit" id="submit">
        <div id="chartdiv"></div>

I am taking date format as "DD-MM-YYYY". Why is this error occuring?

4

1 回答 1

0

The plugin assumes that the dates are already date objects. Since you're using string dates, you need to either convert the dates to date objects prior to adding them to the dataProvider, or update the plugin to convert the string dates to date objects for you.

If you're using a string-based date, you have to set dataDateFormat so the chart knows how to parse your dates correctly. Your string dates in the dataProvider that you're generating in your generateChartData function are actually in "MM-DD-YYYY" format, so you'll want to set dataDateFormat: "MM-DD-YYYY" in the top level of your chart config:

chart = AmCharts.makeChart("chartdiv", {
  // ...
  "dataDateFormat": "MM-DD-YYYY",
  // ...
}

From there, you'll want to update the plugin to check if setFullYear is a function of that data point, and convert it to a date object first before having it set the base year using AmCharts.stringToDate:

  AmCharts.addInitHandler(function(chart) {
    AmCharts.baseYearInitialize = function(chart) {
      for (var x = 0; x < chart.dataSets.length; x++) {
        var ds = chart.dataSets[x];
        if (ds.baseYear !== undefined) {
          for (var i = 0; i < ds.dataProvider.length; i++) {
            var dp = ds.dataProvider[i];
            // if this is not a date object (i.e. setFullYear is not defined) convert it using AmCharts.stringToDate and your chart's dataDateFormat)
            if (!dp[ds.categoryField].setFullYear) {
              dp[ds.categoryField] = AmCharts.stringToDate(dp[ds.categoryField], chart.dataDateFormat);
            }
            dp[ds.categoryField].setFullYear(ds.baseYear);
          }
        }
      }
    }
    AmCharts.baseYearInitialize(chart);
  }, ["stock"]);

I also tweaked your code to check if the input is numeric and a valid array element before adding it to the dataProvider:

var chart;
var SER = [];
//var SER;

first();

function first() {
  for (var i = 0; i < 5; i++) {
    generateChartData(2000 + i);
  }
  //SER = JSON.stringify(SER1);
  //console.log(SER1);
  dd();
}

function generateChartData(year) {
  var firstDate = new Date(year, 0, 1);
  var temp = [];
  for (var i = 0; i < 365; i++) {
    var newDate = new Date(firstDate);
    newDate.setDate(newDate.getDate() + i);
    newDate = ((newDate.getMonth() + 1) < 10 ? "0" + (newDate.getMonth() + 1) : (newDate.getMonth() + 1)) +
      "-" + (newDate.getDate() < 10 ? "0" + newDate.getDate() : newDate.getDate()) +
      "-" + year;
    temp.push({
      date: newDate,
      value: Math.round(Math.random() * (40 + i)) + 100 + i
    });
  }
  SER.push(temp);
}

function dd() {
  AmCharts.addInitHandler(function(chart) {
    AmCharts.baseYearInitialize = function(chart) {
      for (var x = 0; x < chart.dataSets.length; x++) {
        var ds = chart.dataSets[x];
        if (ds.baseYear !== undefined) {
          for (var i = 0; i < ds.dataProvider.length; i++) {
            var dp = ds.dataProvider[i];
            // if this is not a date object (i.e. setFullYear is not defined) convert it using AmCharts.stringToDate and your chart's dataDateFormat)
            if (!dp[ds.categoryField].setFullYear) {
              dp[ds.categoryField] = AmCharts.stringToDate(dp[ds.categoryField], chart.dataDateFormat);
            }
            dp[ds.categoryField].setFullYear(ds.baseYear);
          }
        }
      }
    }
    AmCharts.baseYearInitialize(chart);
  }, ["stock"]);

  chart = AmCharts.makeChart("chartdiv", {
    "type": "stock",
    "theme": "light",
    "dataDateFormat": "MM-DD-YYYY",
    "dataSets": [{
        "title": "2000",
        "fieldMappings": [{
          "fromField": "value",
          "toField": "value"
        }],
        "dataProvider": SER[0],
        "categoryField": "date"
      }
      /* keeping more than one dataset showing error
      , {
          "title": "2001",
          "fieldMappings": [{
              "fromField": "value",
              "toField": "value"
          }],
          "dataProvider": SER[1],
          "categoryField": "date",
          "compared": true,
          "baseYear": 2000
      }, {
          "title": "2002",
          "fieldMappings": [{
              "fromField": "value",
              "toField": "value"
          }
      */
    ],
    "panels": [{
      "title": "Value",
      "categoryAxis": {},
      "dateFormats": 'DD-MM-YYYY',
      "stockGraphs": [{
        "id": "g1",
        "valueField": "value",
        "lineThickness": 2,
        "comparable": true,
        "compareField": "value",
        "balloonText": "[[title]]:<b>[[value]]</b>",
        "compareGraphBalloonText": "[[title]]:<b>[[value]]</b>",
        "compareGraph": {
          "dashLength": 5,
          "lineThickness": 2
        }
      }],
      "stockLegend": {
        "periodValueTextComparing": "[[percents.value.close]]%",
        "periodValueTextRegular": "[[value.close]]"
      }
    }],
    "panelsSettings": {
      "recalculateToPercents": "never"
    },
    "chartScrollbarSettings": {
      "graph": "g1"
    },
    "chartCursorSettings": {
      "valueBalloonsEnabled": true,
      "fullWidth": true,
      "cursorAlpha": 0.1,
      "valueLineBalloonEnabled": true,
      "valueLineEnabled": true,
      "valueLineAlpha": 0.5
    },
    "periodSelector": {
      "position": "bottom",
      "periods": [{
        "period": "MM",
        "selected": true,
        "count": 1,
        "label": "1 month"
      }, {
        "period": "YYYY",
        "count": 1,
        "label": "1 year"
      }, {
        "period": "YTD",
        "label": "YTD"
      }, {
        "period": "MAX",
        "label": "MAX"
      }]
    }

  });
  $('document').ready(function() {
    $('#submit').on('click', function() {
      add(+document.getElementById('year').value);
    });
  });
}

function add(yr) {
  if (!isNaN(yr) && SER[yr - 2000] !== undefined) {
    chart.dataSets.push({
      "title": yr,
      "fieldMappings": [{
        "fromField": "value",
        "toField": "value"
      }],
      "dataProvider": SER[yr - 2000],
      "categoryField": "date",
      "compared": true,
      "baseYear": 2000
    });
    AmCharts.baseYearInitialize(chart);
    chart.validateData();
  }
}
#chartdiv {
  width: 100%;
  height: 500px;
  font-family: Verdana;
  font-size: 12px;
}
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
<script type="text/javascript" src="https://www.amcharts.com/lib/3/amcharts.js"></script>
<script type="text/javascript" src="https://www.amcharts.com/lib/3/serial.js"></script>
<script type="text/javascript" src="https://www.amcharts.com/lib/3/themes/light.js"></script>
<script type="text/javascript" src="https://www.amcharts.com/lib/3/amstock.js"></script>
<input type="text" id="year"><input type="submit" id="submit">
<div id="chartdiv"></div>

于 2017-04-11T15:02:45.057 回答