AngularJS选项卡集中的Chart.js不呈现

Chart.js in AngularJS tabset does not render

本文关键字:js Chart 选项 集中 AngularJS      更新时间:2023-09-26

我正在使用基于Chart.js的AngularJS模块来显示图形。它的工作原理很有魅力,但当我在AngularJS选项卡集中显示图表时,如果它不是第一个选项卡,则该图不会呈现。

  <tabset>
    <tab heading="Tab 1">
        <!-- OK -->
        <canvas class="chart chart-pie" data="[140, 160]" labels="['d1', 'd2']" legend="true"></canvas>
    </tab>
    <tab heading="Tab 2">
        <!-- Does not render -->
       <canvas class="chart chart-pie" data="[140, 160]" labels="['d1', 'd2']" legend="true"></canvas>
    </tab>
  </tabset>

这是JSFiddle。有人能解决这个问题吗?

感谢

正如@Martin所指出的,这是Chart.js在隐藏DOM元素中初始化时没有显示图表的问题(即使显示了隐藏元素,其高度和宽度仍保持在0px)。

此处跟踪此问题。

如果您被初始化为隐藏的选项卡等组件阻止,我将与您分享我的自制解决方案。我已经创建了一个指令,在该指令中我编译了canvas元素。为了能够在需要时刷新元素(例如,当选项卡打开时),我在控制器中观察一个将在选项卡更改时手动更改的属性。

这是我的指示:

app.directive('graphCanvasRefresh', ['$compile', function($compile) {
function link(scope, elem, attrs) {
    function refreshDOM() {
        var markup = '<canvas class="chart chart-pie" id="graph" data="entityGraph.data" labels="entityGraph.labels" legend="true" colours="graphColours" ></canvas>';
        var el = angular.element(markup);
        compiled = $compile(el);
        elem.html('');
        elem.append(el);
        compiled(scope);
    };
    // Refresh the DOM when the attribute value is changed
    scope.$watch(attrs.graphCanvasRefresh, function(value) {
        refreshDOM();
    });
    // Clean the DOM on destroy
    scope.$on('$destroy', function() {
        elem.html('');
    });
};
return  {
    link: link
};
}]);

脏得要命,但这是一个有效的解决方案,您可以在等待Chart.js更新时使用。希望它能帮助到别人。

为@bviale答案添加了一些功能。

app.directive('graphCanvasRefresh', function ($compile, $timeout) {
    return {
        scope:{
            labels: "=",
            data: "=",
            type: "=",
            refresh: "="
        },
        link: function (scope, elem, attrs) {
            function refreshDOM() {
                var markup = '<canvas class="chart chart-' + scope.type + '" id="' + scope.type + scope.$id + '" chart-labels="' + scope.labels + '" ' +
                                                'chart-legend="false"  chart-data="' + scope.data +'" ></canvas>';
                var newEl = $compile(markup)(scope.$parent.$new());
                elem.html(newEl);
                scope.refresh = false;
            };
            // Refresh the DOM when the attribute value is changed
            scope.$watch('refresh', function (value) {
                $timeout(
                refreshDOM(), 100);
            });
            // Clean the DOM on destroy
            scope.$on('$destroy', function () {
                elem.html('');
            });
        }
    };
});