Paul.Whipp Report post Posted April 26, 2015 I'm working on a large existing Angular application that has a requirement for a dashboard. I've added fusion charts via https://github.com/SunGard-Labs/angular-fusioncharts/. It is looking good but I'm concerned at the complexity of the javascript I'm writing. I need 'drill down' on a multi-series chart (which has variable aggregation) to open a tabular report listing the rows corresponding to the data aggregated into the selected bar. I've wired in a link function that opens the relevant page with the filters set depending upon the parameters so it all works but corrupts the global name space with a function (_ARD) to call back into the chart service and feels like I'm jumping through too many hoops to achieve the goal. Is there a better way to do this? angular.module('dhuiApp').factory( 'FCCharts', function () { var charts = {}; var factory = { charts: charts }; function specializeChart(existing_name, specialization_name){ var newChart = jQuery.extend(true, {}, charts[existing_name]); newChart.name = specialization_name; charts[specialization_name] = newChart; } charts.multi_series = { name: 'multi_series', chart: { caption: "Caption", xAxisName: "X Axis", yAxisName: "Y Axis", theme: "fint" }, categories: [ { category: [] } ], dataset: [], seriesNames: [], categoryLabels: [], makeSeriesItem: function(categoryIdx, seriesIdx){ // Make fc link string so we can do our own drill down // Use _ARD global function to get back into this service var categoryLabel = this.categoryLabels[categoryIdx]; var seriesName = this.seriesNames[seriesIdx]; var params = [this.name, categoryLabel, seriesName]; return { value: 0, link: 'j-_ARD-'+params.join('-') }; }, newCategory: function (label){ // confused naming - fc has an extra 'category' layer under categories var seriesIdx, series; var category = {label: label}; var categoryIdx = this.categoryLabels.length; // about to add it this.categories[0].category.push(category); this.categoryLabels.push(label); // Add category to all series var num_series = this.dataset.length; for (seriesIdx = 0; seriesIdx < num_series; seriesIdx++){ series = this.dataset[seriesIdx]; series.data.push(this.makeSeriesItem(categoryIdx, seriesIdx)); } }, newSeries: function(series_name){ var series = { seriesname: series_name, data: [] }; var categoryIdx; var seriesIdx = this.seriesNames.length; // about to add it var num_categories = this.categories[0].category.length; for (categoryIdx = 0; categoryIdx < num_categories; categoryIdx++){ series.data.push(this.makeSeriesItem(categoryIdx, seriesIdx)); } this.dataset.push(series); this.seriesNames.push(series_name); }, getCategory: function(dt, aggregation){ var dt_format = { Day: 'shortDate', Week: 'ww/YY', Month: 'MMM/YY' }[aggregation] || 'MMM/YY'; return dt.format(dt_format); } }; specializeChart('multi_series', 'uploads'); charts.uploads.populate = function(report, from_dt, to_dt, aggregation, linkFn){ var i; var num_rows = report.rows.length; var row, series_name, category_label; var series_data; // do the preamble this.chart.caption = report.title || 'Untitled'; this.chart.xAxisName = aggregation; this.chart.yAxisName = this.chart.caption; // clear any existing data this.linkFn = linkFn; this.categoryLabels = []; this.seriesNames = []; this.categories[0].category = []; this.dataset = []; // Extract the data from the rows for (i = 0; i < num_rows; i++){ row = report.rows[i]; category_label = this.getCategory(row['Added On'], aggregation); if (this.categoryLabels.indexOf(category_label) == -1){ this.newCategory(category_label); } series_name = row['Type']; if (this.seriesNames.indexOf(series_name) == -1){ this.newSeries(series_name); } series_data = this.dataset[this.seriesNames.indexOf(series_name)].data; series_data[this.categoryLabels.indexOf(category_label)].value += 1 } }; factory.getChart = function(chart_name) { return charts[chart_name]; }; factory.linkClicked = function(s){ var params = s.split('-'); console.log(params[0]); console.log(charts[params[0]]); charts[params[0]].linkFn(params.slice(1)); }; return factory; }); /* Not having the event listeners working (might be a better solution if I could get them working): _ARD is used in the link text as the fusion chart function. This is nasty global pollution to link the angular scope to the chart data and I'd love a better method. */ function _ARD(s){ var fc_charts = angular.element(document.querySelector('.ng-scope')).injector().get('FCCharts'); fc_charts.linkClicked(s); } I have wondered about rewriting the angular directives so that I use a specialization of the fusioncharts object as my 'intelligent chart object' (exposing the fusion chart object in the service) but with two angular fusioncharts packages already out there, a third seems like overkill. I'm going to be adding quite a few charts with similar drill down to tables representing the selected underlying data (sometimes through the intermediary of drill down charts) which is why I've set this up so that I can add more charts. Share this post Link to post Share on other sites