I've been trying to rewrite the code for recharts zoom in hook component instead of a class, but I keep having errors. Could someone please tell me what I have done wrong or help me to fix my code?
The error.
Here is the original version from recharts examples
That is how I've done it:
import {
Label,
LineChart,
Line,
CartesianGrid,
XAxis,
YAxis,
Tooltip,
ReferenceArea,
} from "recharts";
const data = [
{ name: 1, cost: 4.11, impression: 100 },
{ name: 2, cost: 2.39, impression: 120 },
{ name: 3, cost: 1.37, impression: 150 },
{ name: 4, cost: 1.16, impression: 180 },
{ name: 5, cost: 2.29, impression: 200 },
{ name: 6, cost: 3, impression: 499 },
{ name: 7, cost: 0.53, impression: 50 },
{ name: 8, cost: 2.52, impression: 100 },
{ name: 9, cost: 1.79, impression: 200 },
{ name: 10, cost: 2.94, impression: 222 },
{ name: 11, cost: 4.3, impression: 210 },
{ name: 12, cost: 4.41, impression: 300 },
{ name: 13, cost: 2.1, impression: 50 },
{ name: 14, cost: 8, impression: 190 },
{ name: 15, cost: 0, impression: 300 },
{ name: 16, cost: 9, impression: 400 },
{ name: 17, cost: 3, impression: 200 },
{ name: 18, cost: 2, impression: 50 },
{ name: 19, cost: 3, impression: 100 },
{ name: 20, cost: 7, impression: 100 },
];
const ZoomIn = () => {
const [data, setData] = useState({});
const [left, setLeft] = useState("dataMin");
const [right, setRight] = useState("dataMax");
const [top, setTop] = useState("dataMax+1");
const [bottom, setBottom] = useState("dataMin-1");
const [top2, setTop2] = useState("dataMax+20");
const [bottom2, setBottom2] = useState("dataMin-20");
const [animation, setAnimation] = useState(true);
const [refAreaLeft, setRefAreaLeft] = useState("");
const [refAreaRight, setRefAreaRight] = useState("");
const getAxisYDomain = (from, to, ref, offset) => {
////
const refData = data.slice(from - 1, to);
let [bottom, top] = [refData[0][ref], refData[0][ref]];
refData.forEach((d) => {
if (d[ref] > top) top = d[ref];
if (d[ref] < bottom) bottom = d[ref];
});
return [(bottom | 0) - offset, (top | 0) + offset];
};
const zoom = () => {
let refAreaLeft = refAreaLeft;
let refAreaRight = refAreaRight;
let data = data;
if (refAreaLeft === refAreaRight || refAreaRight === "") {
setRefAreaLeft("");
setRefAreaRight("");
return;
}
// xAxis domain
if (refAreaLeft > refAreaRight) {
setRefAreaLeft(refAreaRight);
setRefAreaRight(refAreaLeft);
}
// yAxis domain
const [bottom, top] = getAxisYDomain(refAreaLeft, refAreaRight, "cost", 1);
const [bottom2, top2] = getAxisYDomain(
refAreaLeft,
refAreaRight,
"impression",
50
);
setRefAreaLeft("");
setRefAreaRight("");
setData(data.slice());
setLeft(refAreaLeft);
setRight(refAreaRight);
};
const zoomOut = () => {
var data = data;
setData(data.slice);
setRefAreaLeft("");
setRefAreaRight("");
setLeft("dataMin");
setRight("dataMax");
setTop("dataMax+1");
setBottom("dataMin");
setTop2("dataMax+50");
setBottom2("dataMin+50");
};
return (
<div className="highlight-bar-charts" style={{ userSelect: "none" }}>
<button
className="btn update"
onClick={zoomOut}
>
Zoom Out
</button>
<LineChart
width={800}
height={400}
data={data}
onMouseDown={(e) => {
setRefAreaLeft(e.activeLabel);
}}
onMouseMove={(e) => {
setRefAreaRight(e.activeLabel);
}}
onMouseUp={zoom}
>
<CartesianGrid strokeDasharray="3 3" />
<XAxis
allowDataOverflow
dataKey="name"
domain={[left, right]}
type="number"
/>
<YAxis
allowDataOverflow
domain={[bottom, top]}
type="number"
yAxisId="1"
/>
<YAxis
orientation="right"
allowDataOverflow
domain={[bottom2, top2]}
type="number"
yAxisId="2"
/>
<Tooltip />
<Line
yAxisId="1"
type="natural"
dataKey="cost"
stroke="#8884d8"
animationDuration={300}
/>
<Line
yAxisId="2"
type="natural"
dataKey="impression"
stroke="#82ca9d"
animationDuration={300}
/>
{refAreaLeft && refAreaRight ? (
<ReferenceArea
yAxisId="1"
x1={refAreaLeft}
x2={refAreaRight}
strokeOpacity={0.3}
/>
) : null}
</LineChart>
</div>
);
};
export default ZoomIn;
Try to use another variable name
let _refAreaLeft = refAreaLeft;
Related
I have a simple Scatter plot using ChartJS with React. The scatter plot in general has the ability connecting lines between the single datapoints by setting the option 'showLine' in the datasets. I want to have a button to toggle this option (turn showLines on/off). Unfortunately this doesn't work.
If showLines is true in the initalDataSet the change to false doesn't do anything. If showLines is false in the initalDataSet changing it to true crashes ChartJS with the following error:
Uncaught TypeError: line is null
This is a simple example of the problem described:
import React, {
useEffect,
useReducer,
} from "react";
import { Scatter } from "react-chartjs-2";
import Chart from "chart.js/auto";
const initalDataSet = {
datasets: [
{
label: "dataset1",
data: [
{
x: 1,
y: 10,
},
{
x: 3,
y: 15,
},
{
x: 5,
y: 5,
},
{
x: 7,
y: 8,
},
],
borderColor: "red",
showLine: false,
},
{
label: "dataset2",
data: [
{
x: 2,
y: 4,
},
{
x: 4,
y: 6,
},
{
x: 6,
y: 12,
},
{
x: 8,
y: 18,
},
{
x: 10,
y: 10,
},
{
x: 12,
y: 15,
},
{
x: 14,
y: 5,
},
{
x: 16,
y: 8,
},
],
borderColor: "blue",
showLine: false,
},
],
};
const processData = (state, action) => {
switch (action.type) {
case "TOGGLE_LINE":
return {
['datasets']: state.datasets.map((item) => ({
...item,
showLine: (!item['showLine']),
})),
};
default:
return state;
}
};
function App() {
const [plotData, dispatch] = useReducer(processData, initalDataSet);
useEffect(() => {
console.log("debug --->", { datasets: Object.values(plotData) });
}, [plotData]);
return (
<div className="App">
<header className="App-header">
<button
onClick={() => {
dispatch({ type: "TOGGLE_LINE" });
}}
>
Toggle Line View
</button>
<Scatter data={plotData} />
</header>
</div>
);
}
export default App;
I think it must have something to do with the rerendering of the ChartJS component, but I have no idea how to solve it. Does anyone have an idea how to do this?
Thanks!
A possible solution/workaround for this bug can be found here.
first of all thank you for your time.
i need your help with handsontable (page oficial, documentation) . i am trying to create a filter for a custom type cell. key-value-list but i can only “filter” the already rendered data and i can’t re-render more data to always show all filtered data.
here is an example code
https://jsfiddle.net/crifesma/nusahc7p/50/
function BuscarEnSelect_hot(elemento) {
var text = $(elemento.TEXTAREA).val().toLowerCase();
if (text == "") {
for (item of elemento.htEditor.table.rows) {
item.hidden = false;
}
} else {
for (item of elemento.htEditor.table.rows) {
if (item.innerText.toLowerCase().includes(text)) {
item.hidden = false;
} else {
item.hidden = true;
}
}
}
}
/**
* The cell type adds supports for displaing the label value except the key in the key-value
* dropdown editor type.
*/
class KeyValueListEditor extends Handsontable.editors.HandsontableEditor {
prepare(row, col, prop, td, value, cellProperties) {
super.prepare(row, col, prop, td, value, cellProperties);
Object.assign(this.htOptions, {
licenseKey: 'non-commercial-and-evaluation',
data: this.cellProperties.source,
columns: [
{
data: '_id',
},
{
data: 'label',
},
],
hiddenColumns: {
columns: [1],
},
colWidths: cellProperties.width - 1,
beforeValueRender: function (value, {
row,
instance
}) {
return instance.getDataAtRowProp(row, 'label');},
beforeValueRender(value, { row, instance }) {
return instance.getDataAtRowProp(row, 'label');
},
});
if (cellProperties.keyValueListCells) {
this.htOptions.cells = cellProperties.keyValueListCells;
}
if (this.htEditor) {
this.htEditor.destroy();
}
this.htEditor = new Handsontable(this.htContainer, this.htOptions);
this.htEditor.rootElement.style.overflowX = "hidden";
//this.htEditor.rootElement.style.overflowY = "scroll";
this.htEditor.rootElement.style.height = this.htOptions.data.length < 11 ? td.clientHeight * this.htOptions.data.length + 7 + "px" : td.clientHeight * 10 + "px";
this.htEditor.rootElement.style.border = "1px solid #151414";
var w_alto = $(window).height();
var td_position = $(this.TD).offset();
this.htEditor.container.childNodes[0].style.width = td.clientWidth + "px";
this.htEditor.container.childNodes[0].style.maxWidth = td.clientWidth + "px";
this.htEditor.rootElement.style.maxWidth = td.clientWidth + "px";
if ((w_alto - td_position.top) < (td.clientHeight * 11)) {
this.htEditor.rootElement.style.top = ((td.clientHeight * 11) + 4) * -1 + "px"; //el + 2 es por los bordes
} else {
this.htEditor.rootElement.style.top = "";
}
var ddl = this;
$("textarea.handsontableInput").on("input", function (e) {
BuscarEnSelect_hot(ddl);
});
}
setValue(value) {
if (this.htEditor) {
const index = this.htEditor.getDataAtProp('_id').findIndex(id => id === value);
if (index !== -1) {
value = this.htEditor.getDataAtRowProp(index, 'label');
}
}
super.setValue(value);
}
getValue() {
const value = super.getValue();
if (this.htEditor) {
const labels = this.htEditor.getDataAtProp('label');
const row = labels.indexOf(value);
if (row !== -1) {
return this.htEditor.getDataAtRowProp(row, '_id');
}
}
return value;
}
}
const keyValueListValidator = function(value, callback) {
let valueToValidate = value;
if (valueToValidate === null || valueToValidate === void 0) {
valueToValidate = '';
}
if (this.allowEmpty && valueToValidate === '') {
callback(true);
} else {
callback(this.source.find(({ _id }) => _id == value) ? true : false);
}
};
const keyValueListRenderer = function(hot, TD, row, col, prop, value, cellProperties) {
const item = cellProperties.source.find(({
_id
}) => _id === value);
if (item) {
value = item.label;
}
Handsontable.renderers.getRenderer('autocomplete').call(hot, hot, TD, row, col, prop, value, cellProperties);
};
Handsontable.cellTypes.registerCellType('key-value-list', {
editor: KeyValueListEditor,
validator: keyValueListValidator,
renderer: keyValueListRenderer,
});
const example = document.getElementById('example');
const hot = new Handsontable(example, {
data: Handsontable.helper.createSpreadsheetData(10, 10),
colWidths: 100,
width: '100%',
height: 320,
rowHeights: 23,
rowHeaders: true,
colHeaders: true,
afterChange(changes) {
if (!changes) {
return;
}
console.log(this.getDataAtCell(changes[0][0], changes[0][1]));
},
type: 'key-value-list',
source: [
{_id: 1, label: '101 | Mike'},
{_id: 2, label: '102 | Roman'},
{_id: 3, label: '103 | Juan'},
{_id: 4, label: '104 | Mike'},
{_id: 5, label: '105 | Roman'},
{_id: 6, label: '106 | Juan'},
{_id: 7, label: '107 | Mike'},
{_id: 8, label: '108 | Roman'},
{_id: 9, label: '109 | Juan'},
{_id: 10, label: '110 | Mike'},
{_id: 11, label: '111 | Roman'},
{_id: 12, label: '112 | Juan'},
{_id: 13, label: '113 | Mike'},
{_id: 14, label: '114 | Roman'},
{_id: 15, label: '115 | Juan'},
{_id: 16, label: '116 | Mike'},
{_id: 17, label: '117 | Roman'},
{_id: 18, label: '118 | Juan'},
{_id: 19, label: '119 | Mike'},
{_id: 20, label: '120 | Roman'},
{_id: 21, label: '121 | Juan'},
]
});
.wtHider{
width:200px !important;
}
.handsontableInputHolder .wtSpreader .htCore{
width:200px !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/handsontable#latest/dist/handsontable.full.min.js"></script>
<link type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/handsontable#latest/dist/handsontable.full.min.css" />
<div id="example"></div>
I am trying to update the position of a node, based on a click event.
I can see that the data is updated in console, however the x,y coordinates aren't updating. I was expecting the forceSimulation to update the x,y coordinates as soon as the data changed.
Obviously, I have misunderstood how this works. But if you could state where exactly I was wrong in my intuition, that would really help me out. My thought process was that the force simulation would update the the forceX and forceY coordinates based on the foci_dict.
In console : {name: "b", age: 27, index: 0, x: 45.46420808466252, y: 54.94672336907456, …}
The object was updated, however the coordinates didn't update.
<html>
<body>
<canvas id="bubbles" width="1500" height="500"></canvas>
<button onClick="changeMe()"> clicck me </button>
</body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var height = 500;
var width = 1500;
var canvas = d3.select("#bubbles");
var ctx = canvas.node().getContext("2d");
var r = 5;
var data = [
{ name: "a", age: 27 },
{ name: "a", age: 21 },
{ name: "a", age: 37 },
{ name: "b", age: 23 },
{ name: "b", age: 33 },
{ name: "c", age: 23 },
{ name: "d", age: 33 }
];
var foci_points = {
'a': { x: 50, y: 50 },
'b': { x: 150, y: 150 },
'c': { x: 250, y: 250 },
'd': { x: 350, y: 350 }
};
var simulation = d3.forceSimulation()
.force("x", d3.forceX(function(d){
return foci_points[d.name].x;
}))
.force("y", d3.forceY(function(d){
return foci_points[d.name].y;
})
)
.force("collide", d3.forceCollide(r+1))
.force("charge", d3.forceManyBody().strength(10))
.on("tick", update);
simulation.nodes(data);
function update() {
ctx.clearRect(0, 0, width, height);
ctx.beginPath();
data.forEach(drawNode);
ctx.fill();
}
function changeMe(){
data[0].name="b";
console.log(data);
}
function drawNode(d) {
ctx.moveTo(d.x, d.y);
ctx.arc(d.x, d.y, r, 0, 2 * Math.PI);
}
update();
</script>
</html>
There are two issues you have to address:
The forces will not update automatically just because the underlying data has changed. You have to programmatically re-initialize the forces by calling force.initialize(nodes). Given your code this could be somewhat along the following lines:
simulation.force("x").initialize(data); // Get the x force and re-initialize.
simulation.force("y").initialize(data); // Get the y force and re-initialize.
By the time you click the button the simulation will have cooled down or even stopped. To get it going again you have to reheat it by setting alpha to some value greater than alphaMin and by restarting the simulation run.
simulation.alpha(1).restart(); // Reheat and restart the simulation.
These actions can best be done in your changeMe() function.
Have a look at the following snippet for a running demo:
var height = 500;
var width = 1500;
var canvas = d3.select("#bubbles");
var ctx = canvas.node().getContext("2d");
var r = 5;
var data = [{
name: "a",
age: 27
},
{
name: "a",
age: 21
},
{
name: "a",
age: 37
},
{
name: "b",
age: 23
},
{
name: "b",
age: 33
},
{
name: "c",
age: 23
},
{
name: "d",
age: 33
}
];
var foci_points = {
'a': {
x: 50,
y: 50
},
'b': {
x: 150,
y: 150
},
'c': {
x: 250,
y: 250
},
'd': {
x: 350,
y: 350
}
};
var simulation = d3.forceSimulation()
.force("x", d3.forceX(function(d) {
return foci_points[d.name].x;
}))
.force("y", d3.forceY(function(d) {
return foci_points[d.name].y;
}))
.force("collide", d3.forceCollide(r + 1))
.force("charge", d3.forceManyBody().strength(10))
.on("tick", update);
simulation.nodes(data);
function update() {
ctx.clearRect(0, 0, width, height);
ctx.beginPath();
data.forEach(drawNode);
ctx.fill();
}
function changeMe() {
data[0].name = "b";
simulation.force("x").initialize(data);
simulation.force("y").initialize(data);
simulation.alpha(1).restart();
}
function drawNode(d) {
ctx.moveTo(d.x, d.y);
ctx.arc(d.x, d.y, r, 0, 2 * Math.PI);
}
update();
<script src="https://d3js.org/d3.v4.min.js"></script>
<body>
<button onClick="changeMe()"> clicck me </button>
<canvas id="bubbles" width="1500" height="500"></canvas>
</body>
We have the following mixed line chart / bar chart in C3:
a bar chart with two groups (light/dark blue is one group, gray is the
other group)
two other data sets represented as line with stroke-width = 0 that represent the limit for group1 and group2.
How can we place the circle shape for line1 aligned with the bar for group1 and the circle shape for line2 aligned with the two bars of group2?
In the following example, we basically would want one of the two circles to be moved slightly to the right so to align with the center of a group and the other one slightly to the left.
var chartSettings = {
padding: {
left: 120,
right: 120
},
bindto: '#chart',
data: {
x: 'Dates',
type: 'bar',
types: {
line1: 'line',
line2: 'line'
},
groups: [
['data2', 'data3'],
],
colors: {
data1: '#f3e274',
data2: '#85bdde',
data3: '#ccebfb'
},
},
bar: {
width: {
ratio: 0.50
}
},
point: {
r: 8
},
axis: {
x: {
type: 'timeseries',
tick: {
format: '%d-%m-%Y'
}
},
y: {
label: { // ADD
text: '',
position: 'outer-middle'
},
},
}
};
var date1 = new Date(2015, 1, 1, 0,0, 0,0);
var date2 = new Date(2015, 3, 1, 0,0, 0,0);
var date3 = new Date(2015, 6, 1, 0,0, 0,0);
var xAxis = ['Dates', date1, date2,date3];
var line1 = ['line1', 50, 60,55];
var line2 = ['line2', 70, 75,60];
var data1 = ['data1', 40, 35,30];
var data2 = ['data2', 5, 10,10];
var data3 = ['data3', 20, 15,30];
chartSettings.data.columns = [xAxis,
line1,
line2,
data1,
data2,
data3];
c3.generate(chartSettings);
#cr-chart .c3-line-accordatoTotale {
stroke-width: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.11/c3.min.js"></script>
<div id="chart"/>
var chartSettings = {
bindto: '#chart',
data: {
x: 'Dates',
type: 'bar',
types: {
line1: 'line',
line2: 'line'
},
groups: [
['data2', 'data3'],
],
names: {
line1: 'Limit for data1',
line2: 'Limit for data2 + data3',
data1: 'Data1',
data2: 'Data2',
data3: 'Data3'
},
},
bar: {
width: {
ratio: 0.50 // this makes bar width 50% of length between ticks
}
},
point: {
r: 8
},
axis: {
x: {
type: 'timeseries',
tick: {
format: '%d-%m-%Y'
}
},
y: {
label: { // ADD
text: '',
position: 'outer-middle'
}
},
}
};
var date1 = new Date(2016, 1, 1, 0, 0, 0, 0);
var date2 = new Date(2016, 3, 1, 0, 0, 0, 0);
var date3 = new Date(2016, 6, 1, 0, 0, 0, 0);
var xAxis = ['Dates',date1,date2,date3];
var line1 = ['line1', 50, 70,80];
var data1 = ['data1', 30, 40, 60];
var line2 = ['line2', 70, 60,40];
var data2 = ['data2',10,15,20];
var data3 = ['data3',15,30,5];
chartSettings.data.columns = [xAxis,
line1,
line2,
data1,
data2,
data3];
c3.generate(chartSettings);
#chart .c3-line-line1 {
stroke-width: 0px;
}
#chart .c3-line-line2 {
stroke-width: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.11/c3.min.js"></script>
<div id="chart"/>
It would be nice if you attached some jsfiddle.
But at this point I can say that you probably need to look inside .c3-chart-lines container and find desired line eighter by order:
.c3-chart-line:first-child // or last-child?
or by data name:
.c3-chart-line.c3-target-YOUR-ORANGE-DATA-NAME
Hope this helps.
I have a requirement i.e based on the tree view check box selection the value axis need to update.I am using 4 check boxes with 4 value axis.when ever I check the first item corresponding value axis should be changed .3 other axis should in invisible state.
Here I tried with some of the code and updated .
Code:
<div id="treeview"></div>
<div id="example" class="k-content">
<div class="chart-wrapper">
<div id="chart"></div>
</div>
</div>
var valueAxes = [
{ name: "KM",visible:false,
title: { text: "KM" ,visible:false}
},
{ name: "Miles Per Gallon",
title: { text: "Miles Per Gallon" }
},
{
name: "Miles",
title: { text: "Miles " }
},
{
name: "liters per 100km",
title: { text: "liters per 100km" }
}
];
function createChart() {
$("#chart").kendoChart({
legend: {
position: "top"
},
series: [{
type: "column",
data: [20, 40, 45, 30, 50],
stack: true,
name: "on battery",
color: "#003c72"
}, {
type: "column",
data: [20, 30, 35, 35, 40],
stack: true,
name: "on gas",
color: "#0399d4"
}, {
type: "area",
data: [30, 38, 40, 32, 42],
name: "mpg",
color: "#642381"
}, {
type: "area",
data: [7.8, 6.2, 5.9, 7.4, 5.6],
name: "l/100 km",
color: "#e5388a"
}],
valueAxes:valueAxes,
categoryAxis: {
categories: ["Mon", "Tue", "Wed", "Thu", "Fri"],
axisCrossingValues: [0, 0, 10, 10]
}
});
}
$(document).ready(function() {
createChart();
$("#treeview").kendoTreeView({
checkboxes: {
checkChildren: true
},
dataSource: [{
id: 1,
text: "Value axis",
expanded: true,
items: [{
id: 2,
text: "KM"
},
{
id: 3,
text: "Miles Per Gallon"
},
{
id: 4,
text: "Miles "
},
{
id: 5,
text: "liters per 100km"
}]
}]
}).data("kendoTreeView");
$("#treeview").on("change", function (e) {
var chart = $("#chart").data("kendoChart");
var checkedSeries = [];
$("#treeview").find(":checked").each(function() {
var nodeText =$(this).parent().parent().text();
$.each(valueAxes, function(index, valueAxes) {
if (valueAxes.name == nodeText) {
checkedSeries.push(valueAxes);
checkedSeries.visible==="true";
checkedSeries.title.visible===true;
}
});
});
chart.options.valueAxes = checkedSeries;
chart.refresh();
});
});
jsbin: Value axis change
Yes , it is possible to bind and unbind value axis and series at a time.
Change your scripts like below
var valueAxes = [
{
name: "KM", labels: {
format: "{0}"
}, min: 0,
max: 9,
title: { text: "KM" }
},
{
name: "Miles Per Gallon", labels: {
format: "{0}%"
}, min: 0,
max: 5,
title: { text: "Miles Per Gallon" }
},
{
name: "Miles", labels: {
format: "{0}%"
},
title: { text: "Miles " }
},
{
name: "liters per 100km", min: 0,
max: 1,
title: { text: "liters per 100km" }
}];
var series = [{
type: "column",
axis: "KM",
data: [20, 40, 45, 30, 50],
stack: true,
name: "KM",
color: "#003c72"
}, {
type: "column",
data: [20, 30, 35, 35, 40],
axis: "Miles Per Gallon",
stack: true,
name: "Miles Per Gallon",
color: "#0399d4"
}, {
type: "column",
data: [30, 38, 40, 32, 42],
axis: "Miles",
name: "Miles",
color: "#642381"
}, {
type: "column",
axis: "liters per 100km",
data: [7.8, 6.2, 5.9, 7.4, 5.6],
name: "liters per 100km",
color: "#e5388a"
}];
function createChart(inputValueAxes, inputSeries) {
$("#chart").kendoChart({
legend: {
position: "top"
},
series: inputSeries,
valueAxes: inputValueAxes,
categoryAxis: {
categories: ["Mon", "Tue", "Wed", "Thu", "Fri"],
axisCrossingValues: [0, 0, 10, 10]
}
});
}
$(document).ready(function () {
createChart(valueAxes, series);
$("#treeview").kendoTreeView({
checkboxes: {
checkChildren: true
},
dataSource: [{
id: 1,
text: "Value axis",
expanded: true,
items: [{
id: 2,
text: "KM"
},
{
id: 3,
text: "Miles Per Gallon"
},
{
id: 4,
text: "Miles "
},
{
id: 5,
text: "liters per 100km"
}]
}]
}).data("kendoTreeView");
$("#treeview").on("change", function (e) {
var chart = $("#chart").data("kendoChart");
var checkedSeries = [];
var checkedAxes = [];
if ($("#treeview").find(":checked").length !== 0) {
$("#treeview").find(":checked").each(function () {
var nodeText = $(this).parent().parent().text();
$.each(valueAxes, function (index, valueAxes) {
if (valueAxes.name == nodeText.trim()) {
checkedAxes.push(valueAxes);
checkedAxes.visible = true;
}
});
$.each(series, function (index, series) {
if (series.name == nodeText.trim()) {
checkedSeries.push(series);
}
});
});
createChart(checkedAxes, checkedSeries);
}
else {
createChart(checkedAxes, checkedSeries);
}
});
});
Refer this http://jsbin.com/eyibar/49/edit
For convenience, Intially i load all the chart axeses. Its working as you asked....
jsbin: http://jsbin.com/eyibar/37/edit
<html>
<head>
<link href="http://cdn.kendostatic.com/2013.1.319/styles/kendo.common.min.css" rel="stylesheet" type="text/css" />
<link href="http://cdn.kendostatic.com/2013.1.319/styles/kendo.rtl.min.css" rel="stylesheet" type="text/css" />
<link href="http://cdn.kendostatic.com/2013.1.319/styles/kendo.default.min.css" rel="stylesheet" type="text/css" />
<link href="http://cdn.kendostatic.com/2013.1.319/styles/kendo.dataviz.min.css" rel="stylesheet" type="text/css" />
<link href="http://cdn.kendostatic.com/2013.1.319/styles/kendo.dataviz.default.min.css" rel="stylesheet" type="text/css" />
<link href="http://cdn.kendostatic.com/2013.1.319/styles/kendo.mobile.all.min.css" rel="stylesheet" type="text/css" />
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://cdn.kendostatic.com/2013.1.319/js/kendo.all.min.js"></script>
<meta charset="utf-8" />
<title>JS Bin</title>
<style>
#chart { width: 600px; }
</style>
</head>
<body>
<div id="treeview"></div>
<div id="example" class="k-content">
<div class="chart-wrapper">
<div id="chart"></div>
</div>
</div>
<script type="text/javascript">
var valueAxes = [
{
name: "KM",
title: { text: "KM" }
},
{
name: "Miles Per Gallon",
title: { text: "Miles Per Gallon" }
},
{
name: "Miles",
title: { text: "Miles " }
},
{
name: "liters per 100km",
title: { text: "liters per 100km" }
}];
function createChart(valueAxes) {
$("#chart").kendoChart({
legend: {
position: "top"
},
series: [{
type: "column",
data: [20, 40, 45, 30, 50],
stack: true,
name: "on battery",
color: "#003c72"
}, {
type: "column",
data: [20, 30, 35, 35, 40],
stack: true,
name: "on gas",
color: "#0399d4"
}, {
type: "area",
data: [30, 38, 40, 32, 42],
name: "mpg",
color: "#642381"
}, {
type: "area",
data: [7.8, 6.2, 5.9, 7.4, 5.6],
name: "l/100 km",
color: "#e5388a"
}],
valueAxes: valueAxes,
categoryAxis: {
categories: ["Mon", "Tue", "Wed", "Thu", "Fri"],
axisCrossingValues: [0, 0, 10, 10]
}
});
}
$(document).ready(function () {
createChart(valueAxes);
$("#treeview").kendoTreeView({
checkboxes: {
checkChildren: true
},
dataSource: [{
id: 1,
text: "Value axis",
expanded: true,
items: [{
id: 2,
text: "KM"
},
{
id: 3,
text: "Miles Per Gallon"
},
{
id: 4,
text: "Miles "
},
{
id: 5,
text: "liters per 100km"
}]
}]
}).data("kendoTreeView");
$("#treeview").on("change", function (e) {
var chart = $("#chart").data("kendoChart");
var checkedSeries = [];
if ($("#treeview").find(":checked").length != 0) {
$("#treeview").find(":checked").each(function () {
var nodeText = $(this).parent().parent().text();
$.each(valueAxes, function (index, valueAxes) {
if (valueAxes.name == nodeText.trim()) {
checkedSeries.push(valueAxes);
checkedSeries["visible"] = true;
}
});
});
createChart(checkedSeries);
}
else {
createChart(checkedSeries);
}
});
});
</script>
</body>
</html>
I edited your code in that I can able to bind and unbind the valueaxis by calling the creatChart(checkedAxes) function in if condition with length==-1,at that time the series is not updated.
$("#treeview").on("change", function (e) {
var chart = $("#chart").data("kendoChart");
var checkedSeries = [];
var checkedAxes = [];
if ($("#treeview").find(":checked").length !== -1){
$("#treeview").find(":checked").each(function () {
var nodeText = $(this).parent().parent().text();
$.each(valueAxes, function (index, valueAxes) {
if (valueAxes.name == nodeText) {
checkedAxes.push(valueAxes);
checkedAxes.visible = true;
}
});
$.each(series, function (index, series) {
if (series.name == nodeText) {
checkedSeries.push(series);
}
});
});
chart.options.series = checkedSeries;
chart.options.valeAxes = checkedAxes;
chart.refresh();
}
createChart(checkedAxes);
});
but if I tried by without calling the creatChart(checkedAxes) function,the series binded to the chart are updated.
$("#treeview").on("change", function (e) {
var chart = $("#chart").data("kendoChart");
var checkedSeries = [];
var checkedAxes = [];
if ($("#treeview").find(":checked").length !== -1){
$("#treeview").find(":checked").each(function () {
var nodeText = $(this).parent().parent().text();
$.each(valueAxes, function (index, valueAxes) {
if (valueAxes.name == nodeText) {
checkedAxes.push(valueAxes);
checkedAxes.visible = true;
}
});
$.each(series, function (index, series) {
if (series.name == nodeText) {
checkedSeries.push(series);
}
});
});
chart.options.series = checkedSeries;
chart.options.valeAxes = checkedAxes;
chart.refresh();
}
});
I didn't get the both scenarios at a time.sorry,hope you find the solution.
Cheers,
Happy Coding...