I'm a newbie at D3. I have this nice example of a candlestick chart that loads its data from a csv file. I got that example to work but now I want to do the same thing except load the data from an ajax call which returns json data. I can't figure out how to do it.
After reading a few comments, here is my second attempt:
function showChart() {
var margin = {top: 20, right: 20, bottom: 30, left: 50},
width = $(window).width()*0.6 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var parseDate = d3.timeParse("%Y-%m-%d");
var x = techan.scale.financetime().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
var candlestick = techan.plot.candlestick()
.xScale(x)
.yScale(y);
var xAxis = d3.axisBottom().scale(x);
var yAxis = d3.axisLeft().scale(y);
$.ajax("http://www.mycom.net/getQuoteHistory.php?symbol='A'", {
success: function(data) {
console.log("getQuoteHistory:data="+JSON.stringify(data));
var accessor = candlestick.accessor();
data = JSON.parse(data);
var newData = [];
for (var i=0; i<data.length; i++) {
var o = data[i];
var newObj = {};
newObj.date = parseDate(o.Date);
newObj.open = o.Open;
newObj.high = o.High;
newObj.low = o.Low;
newObj.close = o.Close;
newObj.volume = o.Volume;
newData.push(newObj);
}
console.log("getQuoteHistory:newData="+JSON.stringify(newData));
var svg = d3.select("svg")
.data(newData)
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("g").attr("class", "candlestick");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")");
svg.append("g")
.attr("class", "y axis")
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Price ($)");
// Data to display initially
draw(newData.slice(0, newData.length-20));
// Only want this button to be active if the data has loaded
d3.select("button").on("click", function() {
draw(newData);
}).style("display", "inline");
},
error: function() {
console.log("something went wrong in ajax call");
}
});
function draw(data) {
x.domain(data.map(candlestick.accessor().d));
y.domain(techan.scale.plot.ohlc(data, candlestick.accessor()).domain());
svg.selectAll("g.candlestick").datum(data).call(candlestick);
svg.selectAll("g.x.axis").call(xAxis);
svg.selectAll("g.y.axis").call(yAxis);
}
}
The ajax call returns good json array data and it is converted to newData which has the date parsed correctly and the field names in lower case as reqd. Here is a snippet of each:
getQuoteHistory:data="[{\"Symbol\":\"A\",\"Date\":\"2018-06-28\",\"Open\":\"61.13\",\"High\":\"61.64\",\"Low\":\"60.42\",\"Close\":\"61.29\",\"Volume\":\"15641\"},{\"Symbol\":\"A\",\"Date\":\"2018-06-29\",\"Open\":\"61.68\",\"High\":\"62.47\",\"Low\":\"61.57\",\"Close\":\"61.84\",\"Volume\":\"18860\"},
getQuoteHistory:newData=[{"date":"2018-06-28T06:00:00.000Z","open":"61.13","high":"61.64","low":"60.42","close":"61.29","volume":"15641"},{"date":"2018-06-29T06:00:00.000Z","open":"61.68",
Now the failure happens in the draw function on this line:
svg.selectAll("g.candlestick").datum(data).call(candlestick);
where the chrome javascript console shows "svg is not defined".
But it is defined in the html:
<svg></svg>
Even if I pass svg as a parameter to draw method, then it says "cannot read property selectAll of undefined".
Any ideas how to get this to work from a json array instead of a csv file?
d3.jsonand if it is csv, used3.csvto fetch the remote data.data. The error is probably telling you thatdatais not an array.candlestick.accessor()would not find the data.