最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Morris JS Chart Not Loading in Twitter Bootstrap Tab Pane - Stack Overflow

programmeradmin1浏览0评论

I have a Morris JS chart trying to load within a Twitter Bootstrap tab pane. The tabs work fine, but the chart will not load.

It looks like this article discusses the problem:

How would I translate their solution into my Rails code?

Here is my code:

View:

<!-- Nav tabs -->
<ul class="nav nav-tabs">
  <li class="active"><a href="#home" data-toggle="tab">Home</a></li>
  <li><a href="#profile" data-toggle="tab">Profile</a></li>
  <li><a href="#messages" data-toggle="tab">Messages</a></li>
  <li><a href="#settings" data-toggle="tab">Settings</a></li>
</ul>

<!-- Tab panes -->
<div class="tab-content">
  <div class="tab-pane active" id="home">...</div>
  <div class="tab-pane" id="profile">
    <%= content_tag :div, "", id: "info_chart", data: { info: @chart_data } %>
  </div>
  <div class="tab-pane" id="messages">...</div>
  <div class="tab-pane" id="settings">...</div>
</div>

Application.JS

$('#myTab a').click(function (e) {
  e.preventDefault()
  $(this).tab('show')
})

ControllerName.js.coffee

$ ->
  # only use morris if the post chart element is on the page.
  if $('#info_chart').length > 0
    Morris.Bar
      element: 'info_chart'
      data: $('#info_chart').data('info')
      xkey: 'x'
      ykeys: ['y']
      labels: ['label']

I have a Morris JS chart trying to load within a Twitter Bootstrap tab pane. The tabs work fine, but the chart will not load.

It looks like this article discusses the problem: http://www.doidea.se/blog/morris-js-charts-in-bootstrap-tabs

How would I translate their solution into my Rails code?

Here is my code:

View:

<!-- Nav tabs -->
<ul class="nav nav-tabs">
  <li class="active"><a href="#home" data-toggle="tab">Home</a></li>
  <li><a href="#profile" data-toggle="tab">Profile</a></li>
  <li><a href="#messages" data-toggle="tab">Messages</a></li>
  <li><a href="#settings" data-toggle="tab">Settings</a></li>
</ul>

<!-- Tab panes -->
<div class="tab-content">
  <div class="tab-pane active" id="home">...</div>
  <div class="tab-pane" id="profile">
    <%= content_tag :div, "", id: "info_chart", data: { info: @chart_data } %>
  </div>
  <div class="tab-pane" id="messages">...</div>
  <div class="tab-pane" id="settings">...</div>
</div>

Application.JS

$('#myTab a').click(function (e) {
  e.preventDefault()
  $(this).tab('show')
})

ControllerName.js.coffee

$ ->
  # only use morris if the post chart element is on the page.
  if $('#info_chart').length > 0
    Morris.Bar
      element: 'info_chart'
      data: $('#info_chart').data('info')
      xkey: 'x'
      ykeys: ['y']
      labels: ['label']
Share Improve this question edited Mar 4, 2014 at 8:08 user2270029 asked Mar 1, 2014 at 1:25 user2270029user2270029 87114 silver badges27 bronze badges 1
  • Any errors in the console? Do you see the chart svg tags in the page source? – steakchaser Commented Mar 1, 2014 at 3:46
Add a comment  | 

5 Answers 5

Reset to default 12

Found a solution to my situation for a single chart on tabs that wasn't display properly:

Save your graph as a variable:

var usage_graph = Morris.Line({
  // config
});

Then listen for changes on the tabs, and redraw the graph:

$('ul.nav a').on('shown.bs.tab', function (e) {
    usage_graph.redraw();
});

I hope this helps someone else.

The top answer is partially correct. The problem, however, is the svg is not resized. In order to make sure the svg is resized, you can modify it by css:

    if ($('#morris-stacked-bar-graph').length > 0) {
        var morris_bar = Morris.Bar({
            element: 'morris-stacked-bar-graph',
            data: [
                {x: '2011 Q1', y: 3, z: 2, a: 3},
                {x: '2011 Q2', y: 2, z: null, a: 1},
                {x: '2011 Q3', y: 0, z: 2, a: 4},
                {x: '2011 Q4', y: 2, z: 4, a: 3}
            ],
            xkey: 'x',
            ykeys: ['y', 'z', 'a'],
            labels: ['Y', 'Z', 'A'],
            stacked: true,
            barColors: $('#morris-stacked-bar-graph').data('colors').split(',')
        });
        $('ul.nav a').on('shown.bs.tab', function (e) {
            morris_bar.redraw();
            $('svg').css({ width: '100%' });
        });
    }

First, you want to check that you are using the correct version of morris.js, the current master branch on github has the redraw() function.

Second: Make sure that you are able to print a graph in the dom on say, you first active tab.

Third: Add another graph element in a tab that is not active, add data-identifiers for each tab to be able to redraw multiple graphs using:

$('ul.nav a').on('shown.bs.tab', function (e) {
    var types = $(this).attr("data-identifier");
    var typesArray = types.split(",");
    $.each(typesArray, function (key, value) {
        eval(value + ".redraw()");
    })
});

This js will determine which data-identifiers are concerned whenever a tab is 'shown', you can have multiple graph elements separated by commas for instance. It will then take the value/values of the identifier, which obviously would be the same as your graph elements and call the redraw() function on them.

I see no need to make it more railsy than that for this, you could always convert to coffeescript ofcourse, but this should work.

This code is working for me, try it if you have multiple Chart on one tab:

$(document).on('shown.bs.tab', 'a[data-toggle="tab"]', function (e) {
$.each(yourarray, function (index, value) {
                value.redraw();
            });
        });

I was having the exact same problem, but in my case none of the above solutions worked.

What worked for me was to use the jquery ui tabs instead (link). These worked like a charm.

Your code would only need slight re-writing. Instead of

<!-- Nav tabs -->
<ul class="nav nav-tabs">
  <li class="active"><a href="#home" data-toggle="tab">Home</a></li>
  <li><a href="#profile" data-toggle="tab">Profile</a></li>
  <li><a href="#messages" data-toggle="tab">Messages</a></li>
  <li><a href="#settings" data-toggle="tab">Settings</a></li>
</ul>

<!-- Tab panes -->
<div class="tab-content">
  <div class="tab-pane active" id="home">...</div>
  <div class="tab-pane" id="profile">
    <%= content_tag :div, "", id: "info_chart", data: { info: @chart_data } %>
  </div>
  <div class="tab-pane" id="messages">...</div>
  <div class="tab-pane" id="settings">...</div>
</div>

write:

    <!-- Nav tabs and Panes-->
<div id="tabs">
    <ul>
      <li class="active"><a href="#home" data-toggle="tab">Home</a></li>
      <li><a href="#profile" data-toggle="tab">Profile</a></li>
      <li><a href="#messages" data-toggle="tab">Messages</a></li>
      <li><a href="#settings" data-toggle="tab">Settings</a></li>
    </ul>


      <div  id="home">...</div>
      <div  id="profile">
        <%= content_tag :div, "", id: "info_chart", data: { info: @chart_data } %>
      </div>
      <div id="messages">...</div>
      <div  id="settings">...</div>
 </div>

And then you just add this script:

 <script>
  $(function() {
    $( "#tabs" ).tabs();
  });
  </script>

I hope this helps.

BTW all the fiddles I've found that try to catch event 'shown.bs.tab' don't work anymore for some reason.

发布评论

评论列表(0)

  1. 暂无评论