I'm using Kendo UI to add charts to an AngularJS application.
The charts work fine, except when they start hidden: if a chart's <div />
is hidden when the chart is initialized, when the chart's <div />
is shown the chart does not span the whole available width and is rendered in only a fraction of the available space.
You can test this issue with the following code:
<div data-ng-app='myModule' data-ng-controller='myController' data-ng-cloak>
<p>
<button data-ng-click='toggleMyChart()'>
Toggle chart
</button>
</p>
<div data-kendo-chart='myChart' data-k-options='myChartOptions' data-ng-show='isMyChartVisible'>
</div>
</div>
<script>
(function () {
angular
.module('myModule', ['kendo.directives'])
.controller('myController', ['$scope', function ($scope) {
$scope.isMyChartVisible = false;
$scope.toggleMyChart = function () {
$scope.isMyChartVisible = !$scope.isMyChartVisible;
};
$scope.myChartOptions = {
'dataSource': {
'data': [
{ 'category': '1', 'value': '4' },
{ 'category': '2', 'value': '8' },
{ 'category': '3', 'value': '15' },
{ 'category': '4', 'value': '16' },
{ 'category': '5', 'value': '23' },
{ 'category': '6', 'value': '42' }
]
},
'series': [
{ 'field': 'value', 'name': 'Numbers' }
],
'seriesDefaults': {
'categoryField': 'category',
'type': 'bar'
}
};
}]);
})();
</script>
Demo: http://codepen.io/albireo/pen/AeHui/?editors=101
The problem seems to be not strictly related to AngularJS, as it happens when using jQuery too:
<p>
<button id='toggleChart'>
Toggle chart
</button>
</p>
<div id='chart'>
</div>
<script>
(function () {
'use strict';
$(document).ready(function () {
var isChartVisible = false;
$('#toggleChart').click(function () {
isChartVisible = !isChartVisible;
if (isChartVisible) {
$('#chart').show();
} else {
$('#chart').hide();
}
});
$('#chart').hide();
$('#chart').kendoChart({
'dataSource': {
'data': [
{ 'category': '1', 'value': '4' },
{ 'category': '2', 'value': '8' },
{ 'category': '3', 'value': '15' },
{ 'category': '4', 'value': '16' },
{ 'category': '5', 'value': '23' },
{ 'category': '6', 'value': '42' }
]
},
'series': [
{ 'field': 'value', 'name': 'Numbers' }
],
'seriesDefaults': {
'categoryField': 'category',
'type': 'bar'
}
});
});
})();
</script>
Demo: http://codepen.io/albireo/pen/mvBap?editors=101
The problem seems to be known to Telerik:
when you click the button and show the chart it is already rendered and takes the default chart's width
Quote taken from Kendo UI Chart does not use the entire width of the div when the div containing the chart is hidden.
Indeed, if I add a .redraw()
to the jQuery example everything works correctly:
$('#toggleChart').click(function () {
isChartVisible = !isChartVisible;
if (isChartVisible) {
$('#chart').show();
} else {
$('#chart').hide();
$('#chart').data('kendoChart').redraw();
}
});
Demo: http://codepen.io/albireo/pen/atkLg?editors=101
Then I tried to add the same call to the AngularJS test too but it didn't work, nothing changed:
$scope.toggleMyChart = function () {
$scope.isMyChartVisible = !$scope.isMyChartVisible;
if ($scope.isMyChartVisible) {
$scope.myChart.redraw();
}
};
Demo: http://codepen.io/albireo/pen/IFcbw?editors=101
I think this is caused because in the AngularJS example the container is shown asynchronously, leading to then .redraw()
being fired before the <div />
is shown, nullifying its effect.
This seems to be backed by adding a timeout to the .redraw()
call, which yields the correct behaviour:
$scope.toggleMyChart = function () {
$scope.isMyChartVisible = !$scope.isMyChartVisible;
if ($scope.isMyChartVisible) {
$timeout(function () {
$scope.myChart.redraw();
}, 10);
}
};
Demo: http://codepen.io/albireo/pen/jDoew?editors=101
However, this hack adds another problem: a timeout adds an annoying "flash" to the page, the chart first is shown in its "small" state, then disappears for a moment while being rendered and finally reappears with the correct size.
How can I get the desired result (have an hidden chart span the whole available space when being shown) without side effects?
P.s. The problem seems to appear only when the chart is created hidden, if an existing chard is hidden and then shown again it works correctly, see http://codepen.io/albireo/pen/vfzeu?editors=101.