Using Highcharts Directive with a Carousel

1,037 views
Skip to first unread message

Matt Raible

unread,
Feb 28, 2013, 1:52:45 PM2/28/13
to ang...@googlegroups.com
Hello,

I'm trying to use the following Highcharts directive with a carousel component. 


Using my own template and Twitter's Bootstrap, I have the following:

<div id="chartCarousel1" class="carousel slide">
    <div class="carousel-inner">
        <div class="item chart"
             ng-repeat="widget in widgets | filter: {type: 'chart'} | orderBy: 'order'"
             ng-class="{active: $index == 0}">
            <chart class="widget" value="{{widget}}" type="{{widget.chartType}}"></chart>
        </div>
    </div>

    <a class="left carousel-control" href="#chartCarousel1" data-slide="prev"
       ng-show="(widgets | filter: {type: 'chart'}).length > 1">&lsaquo;</a>
    <a class="right carousel-control" href="#chartCarousel1" data-slide="next"
       ng-show="(widgets | filter: {type: 'chart'}).length > 1">&rsaquo;</a>
</div>

However, this results in the following error:

TypeError: Cannot read property 'length' of undefined at Object.ob.setMaxTicks (http://localhost:8080/ats/cacheable/2013_02_28_08_41/js/UIv8/tbe-dashboard.js:626:24) at Object.ob.setScale (http://localhost:8080/ats/cacheable/2013_02_28_08_41/js/UIv8/tbe-dashboard.js:628:20) at http://localhost:8080/ats/cacheable/2013_02_28_08_41/js/UIv8/tbe-dashboard.js:688:461 at Array.forEach (native) at each.Array.forEach.c (http://localhost:8080/ats/cacheable/2013_02_28_08_41/js/UIv8/tbe-dashboard.js:532:100) at Object.sb.render (http://localhost:8080/ats/cacheable/2013_02_28_08_41/js/UIv8/tbe-dashboard.js:688:443) at Object.sb.firstRender (http://localhost:8080/ats/cacheable/2013_02_28_08_41/js/UIv8/tbe-dashboard.js:692:353) at Object.sb.init (http://localhost:8080/ats/cacheable/2013_02_28_08_41/js/UIv8/tbe-dashboard.js:667:405) at Object.sb (http://localhost:8080/ats/cacheable/2013_02_28_08_41/js/UIv8/tbe-dashboard.js:526:204) at Object.fn (http://localhost:8080/ats/cacheable/2013_02_28_08_41/js/UIv8/tbe-dashboard.js:815:33)

This seems to be caused by the following css in Bootstrap:

.carousel-inner > .item { display: none }

If I add an override with "display: block" to my stylesheet, everything works, but the charts are stacked instead of in a carousel. The good news is all the charts are rendered successfully.

A seemingly better solution is to modify the directive to show/hide the "item" element so Highcharts is able to write to it. The code for this is below:

link: function (scope, element, attrs) {
    var chartsDefaults = {
        chart: {
            renderTo: element[0],
            type: attrs.type || null,
            height: attrs.height || null,
            width: attrs.width || null
        }
    };

    $(element[0]).parent().show();

    //Update when charts data changes
    scope.$watch(function () {
        return attrs.value;
    }, function (value) {
        if (!attrs.value) return;
        // We need deep copy in order to NOT override original chart object.
        // This allows us to override chart data member and still the keep
        // our original renderTo will be the same
        var deepCopy = true;
        var newSettings = {};
        $.extend(deepCopy, newSettings, chartsDefaults, JSON.parse(attrs.value));
        var chart = new Highcharts.Chart(newSettings);
        if (scope.$index > 0) {
            $(element[0]).parent().hide();
        }
    });
}

This seems to work (or at least stops the error), but only the first chart is written. The rest don't seem to be "activated" properly when I navigate to them. Probably because of something to do with hiding them. I've tried just setting "display" to block and none (instead of show and hide), but that doesn't seem to work either.

This same behavior happens when using the carousel directive from angular-ui-bootstrap.

Any ideas for a workaround?

Thanks,

Matt

Matt Raible

unread,
Mar 1, 2013, 2:50:55 PM3/1/13
to AngularJS
I was able to fix this by modifying my "chart" directive as follows:

if (element.parent().not(':visible')) {
element.parent().show();
}

var chart = new Highcharts.Chart(newSettings);

if (scope.$last) {
$.each(element.parent().siblings(), function() {
$(this).attr('style', '');
});
element.parent().attr('style', '');
}

On Feb 28, 11:52 am, Matt Raible <mrai...@gmail.com> wrote:
> Hello,
>
> I'm trying to use the following Highcharts directive with a carousel
> component.
>
> https://github.com/rootux/angular-highcharts-directive/blob/master/sr...
>
> Using my own template and Twitter's Bootstrap, I have the following:
>
> <div id="chartCarousel1" class="carousel slide">
>     <div class="carousel-inner">
>         <div class="item chart"
>              ng-repeat="widget in widgets | filter: {type: 'chart'} |
> orderBy: 'order'"
>              ng-class="{active: $index == 0}">
>             <chart class="widget" value="{{widget}}"
> type="{{widget.chartType}}"></chart>
>         </div>
>     </div>
>
>     <a class="left carousel-control" href="#chartCarousel1"
> data-slide="prev"
>        ng-show="(widgets | filter: {type: 'chart'}).length > 1">&lsaquo;</a>
>     <a class="right carousel-control" href="#chartCarousel1"
> data-slide="next"
>        ng-show="(widgets | filter: {type: 'chart'}).length > 1">&rsaquo;</a>
> </div>
>
> However, this results in the following error:
>
> TypeError: Cannot read property 'length' of undefined at
> Object.ob.setMaxTicks (http://localhost:8080/ats/cacheable/2013_02_28_08_41/js/UIv8/tbe-dash...<http://localhost:8080/ats/cacheable/2013_02_28_08_41/js/UIv8/tbe-dash...>)
> at Object.ob.setScale (http://localhost:8080/ats/cacheable/2013_02_28_08_41/js/UIv8/tbe-dash...<http://localhost:8080/ats/cacheable/2013_02_28_08_41/js/UIv8/tbe-dash...>)
> athttp://localhost:8080/ats/cacheable/2013_02_28_08_41/js/UIv8/tbe-dash...<http://localhost:8080/ats/cacheable/2013_02_28_08_41/js/UIv8/tbe-dash...>at Array.forEach (native) at each.Array.forEach.c (http://localhost:8080/ats/cacheable/2013_02_28_08_41/js/UIv8/tbe-dash...<http://localhost:8080/ats/cacheable/2013_02_28_08_41/js/UIv8/tbe-dash...>)
> at Object.sb.render (http://localhost:8080/ats/cacheable/2013_02_28_08_41/js/UIv8/tbe-dash...<http://localhost:8080/ats/cacheable/2013_02_28_08_41/js/UIv8/tbe-dash...>)
> at Object.sb.firstRender (http://localhost:8080/ats/cacheable/2013_02_28_08_41/js/UIv8/tbe-dash...<http://localhost:8080/ats/cacheable/2013_02_28_08_41/js/UIv8/tbe-dash...>)
> at Object.sb.init (http://localhost:8080/ats/cacheable/2013_02_28_08_41/js/UIv8/tbe-dash...<http://localhost:8080/ats/cacheable/2013_02_28_08_41/js/UIv8/tbe-dash...>)
> at Object.sb (http://localhost:8080/ats/cacheable/2013_02_28_08_41/js/UIv8/tbe-dash...<http://localhost:8080/ats/cacheable/2013_02_28_08_41/js/UIv8/tbe-dash...>)
> at Object.fn (http://localhost:8080/ats/cacheable/2013_02_28_08_41/js/UIv8/tbe-dash...<http://localhost:8080/ats/cacheable/2013_02_28_08_41/js/UIv8/tbe-dash...>

Rafael Motta

unread,
Mar 19, 2013, 3:33:06 PM3/19/13
to ang...@googlegroups.com
Man, i had a problem that i think was similar to yours. 
I solved it putting in the <div class="item"> the class next.
It became <div class="item next">. 
Then the charts worked as i expected.

see ya

Rafael Motta

Christoph Albrecht

unread,
Sep 12, 2014, 4:40:23 PM9/12/14
to ang...@googlegroups.com
Hey Rafael,

Thanks a lot for this tip. Works great and solves the problem in very easy way! (Save me hours! :) )
Reply all
Reply to author
Forward
0 new messages