So There is one line chart that is working fine so now I am trying to add 2 more graphs so that I can see the interaction between them by cross-filtering.
When I select range interval from bar chart then I get this error:
VM357 dc.js:3697 Uncaught TypeError: Cannot read property 'domain' of undefined
at prepareXAxis (VM345 dc.js:3697)
at drawChart (VM345 dc.js:4426)
at Object._chart._doRedraw (VM345 dc.js:4415)
at Object._chart.redraw (VM345 dc.js:2138)
at Object.dc.redrawAll (VM345 dc.js:279)
at Object._chart.redrawGroup (VM345 dc.js:2190)
at Object._chart.applyBrushSelection (VM345 dc.js:4296)
at VM345 dc.js:4289
at VM345 dc.js:1241
Working demo + Code:
https://blockbuilder.org/ninjakx/ad4ab375e1a14f3e151c5b13a60ecef5
that line chart has 2 types:
1) composite chart which is defined under function comp_chart (Line no: 396-434)
2) Single Line chart which is defined next to the above.
So all the graphs are getting rendered in line 558.
Those 2 kind of line chart is rendered in function setup() line no: 529 also.
That bar chart is defined under composite2
I don't know how to tackle this error.
Edit:
See it works for me right now.
Sorry, this is not a complete answer, because I don't have time to debug your project for you. I have diagnosed the specific problem and I have a suggestion only.
The specific problem you are encountering is that you have initialized two different charts into the same div, but only one of them is active at a time:
var composite = dc.compositeChart("#line-chart");
var composite2 = dc.barChart("#line-chart2");
var linechart = dc.lineChart("#line-chart")
When you start out, you have the composite chart initialized in #line-chart, but the other line chart is not initialized. Unfortunately, dc.js will still try to draw it! So that is why it is crashing.
My suggestion is to only use the composite chart, and re-initialize it with only one child chart when you display an individual state.
Otherwise you would have to go through the tedium of adding and removing charts from the chart registry, which is error-prone.
Notice that if you first switch to an individual state and then filter on the bar chart, you don't get the same error, but you run into problems with your legend toggling code instead, since it is still trying to read/update the composite chart even though it no longer exists.
I think it's going to be a headache to condition all of your code on which chart is active in the div, and it should be easier to only have one chart per div, especially since the line chart functionality is a strict subset of the composite.
Related
I've created 2 pie charts in an analysis and one of them seems to have its labels overlapping while the other has callouts and prevents any overlaps. I have created them in the exact same way and they both have the same properties.
Another strange thing is, this doesn't occur all the time. sometimes when I open an analysis/dashboard, both the pie charts look fine and when I refresh the page or come back to it later, then one of the chart has overlapping labels. Can anyone help me fix this.
Check out MOS Doc ID Doc ID 2260470.1 - you'll have to live with it at the moment
I am trying to understand and implement the D3 reusable chart pattern.
See sample implementation.
Here the updatableChart is called after selecting the id '#updatableChart'.
Question 1:
If I want to adjust the height parameter by calling as below, in subsequent code, it duplicates the chart.
d3.select('#updatableChart')
.call(updatableChart.height(450));
How should I use this pattern and update the height without affecting the original chart ?
Question 2:
Now if I need another chart, say, under div id '#updatableChart2', I can still call and get the chart using code below.
d3.select('#updatableChart2')
.call(updatableChart)`
But when I try to adjust the height by simply saying updatableChart.height(500); it affects only the second chart. How can I be specific in choosing the chart instance to work on ?
Thank you.
Answer 1:
The reason the chart is drawn again, is because I am calling the updatableChart.height(450) within a D3 selection. Instead it should have been called simply as updatableChart.height(450), to adjust the height.
Answer 2:
The problem was that the same chart object is attached into different div elements.
If another chart is needed under a different div, then the original barchart() should have been instantiated into another copy, say var updatableChart2 = barChart() and used further.
I created a grouped-stacked composite chart using dc.js.
I am wondering if I can add a filterHandler to a composite chart.
I want to filter on each stacks.
It seems that, there is no straight forward way to build a composite chart and hook the parent chart to the volumeChart that would filter all the individual child components at once via dc.js, as Gordon suggested. I came up with a solution for one of my dashboards which is not so modular but works fine & also keep in mind the downsides to this approach pointed out below.
For the above dashboard to work, I defined 3 barCharts and 3 lineCharts overlaid on top the barCharts and chaining them all together linearly to volumeChart.
Although this works fine with a fixed y-axis scale, lineChart fails to align with the barCharts when the I set elasticY(true) on all of them, since the lineChart components seem to pic its own yMax and when I pass the yMax value as window.value from barCharts to the lineChart via .on('renderlet'..., again I fail to read these values due the misalignment of individual chart render times. And of course when I overlay the lineCharts I intrinsically loose/block the interaction with the barCharts and use the line moving average tooltips to view bar data.
I have not tried this yet but found a better way to do the same from Scott Miller - https://stackoverflow.com/a/25188909/5743716
Hope it helps!
In D3 I am working on customizing and adding to #Rengel's timeline (link shown in JS Fiddle.
I've successfully created a similar timeline based on tracks, and it also allows users to filter project data based on checkbox values. Each piece of data now has a tooltip, and there are letters from another dataset populating underneath the projects in the same svg container. Now finally I want to add a brush like this one - wrobstory's from the blocks website.
I have only recently started to work on brush events so I am very much a noob, which is why I am unsure how I am going wrong. There is a JS Fiddle I created at: https://jsfiddle.net/rootseire/2vq8028o/2/ which shows everything working before the brush gets called. When I select a section of the timeline, the brush appears, it calculates indexes and extent. But it changes the y state of the year and the year text then transitions down the page.
I have been trying to see why this is happening, but I think I need to step back from the code as it might be just that I am not referencing the correct element. Here is the code for when the mouse pointer drags over the interface:
vis.on('mousedown', function(){
brush_elm = vis.select(".brush").node();
new_click_event = new Event('mousedown');
new_click_event.pageX = d3.event.pageX;
new_click_event.clientX = d3.event.clientX;
new_click_event.pageY = d3.event.pageY;
new_click_event.clientY = d3.event.clientY;
brush_elm.dispatchEvent(new_click_event);
});
But I think it might have something to do with the .points selector. How can I make the brush target the x-axis, the project rectangles and the letters together?
Thanks in advance,
P
I have an annotated timeline chart that gets new data over ajax. It's working fine, new points come in and I redraw the graph. My graph has two lines, so there are two labels in the legend on top. For whatever stupid reason, every single time the graph is redrawn, the legend labels swap places! So it will say
Foo 5.2 Bar 3.6
And then I'll refresh (and there will be no new data, so the call to redraw is 100% identical to the previous one) and now it says
Bar 3.6 Foo 5.2
In the respective red and blue, of course. What on earth would possess the applet to do this? Is there any way I can control the order of legend labels? I couldn't find anything about it in the official documentation.
Try using google.visualization.DataTable. For example:
dataTable = new google.visualization.DataTable({cols:graphColumns, rows:graphRows});
chart = new google.visualization.AnnotatedTimeLine($('#chart_div')[0]);
chart.draw(dataTable)
I use it this way and don't have any problems with my legend values.