Kendo UI graph does not use all available space if shown, if created hidden

I am using Kendo UI to add charts to my AngularJS app.

Charts work fine, except when they start to hide: if the chart <div />

is hidden when the chart is initialized, when the chart is shown <div />

, the chart does not span the entire available width and only a fraction of the available space is displayed.

You can test this problem 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 appears to be not strictly AngularJS related, as it does when using jQuery:

<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 it is already displayed and takes the default chart width

Quote taken from Kendo UI Chart does not use the entire div width when the div containing the chart is hidden .

Indeed, if I add .redraw()

jQuery to the 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 adding the same call to the AngularJS test, 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 because the AngularJS example shows the container asynchronously, which causes it to .redraw()

run before it appears <div />

, which negates its effect.

It seems to have something to do with adding a timeout to the call .redraw()

, which gives the correct behavior:

$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: the timeout adds an annoying "flash" to the page, first the chart is displayed in a "small" state, then disappears for a moment when displayed, and finally appears at the correct size.

How can I get the desired result (have a hidden diagram covering all the available space when shown) without side effects?

Ps The problem only seems to appear when the chart is created hidden, if the existing stroke is hidden and then shown again, it works correctly, see http://codepen.io/albireo/pen/vfzeu?editors=101 .

+3


source to share


1 answer


A little later, maybe. But I found this post to solve a similar problem. I just removed the 10ms delay in your $ timeout, which seems to eliminate the annoying flicker.

I changed this

$timeout(function () {
   $scope.myChart.redraw();
}, 10);

      



to

$timeout(function () {
   $scope.myChart.redraw();
});

      

See the demo here.

+2


source







All Articles