Dynamically update Google Chart using AngularJS and Java - javascript
My goal is to dynamically update the array table for google charts.
I am unable update the content of the Google Chart with the data I'm passing from my Java class. I use tempGraph2 to initialize the graph when the page load but when the user clicks on a file name, the java class passes a formatted string as follows but it is not updating the content of the chart:
[["Domain names","Domain Count"],["Positive-Female",6],["Positive- GenderNeutral",0],["Positive-Male",17],["Neutral-Female",6],["Neutral-GenderNeutral",0],["Neutral-Male",8],["Negative-Female",3],["Negative-GenderNeutral",0],["Negative-Male",19]]
The value is linked using ng-model as follows:
<div ng:model="tempGraph2"
qn:barcolumns="[
{type:'string', name: 'Categories'},
{type:'number', name: 'Counts'}]"
qn:bar="{
legend : {position: 'none'},
chart: { subtitle: 'popularity by percentage' },
chartArea: {height: 400},
backgroundColor: '#F7F7F7'}"></div>
<div ng:model="tempGraph2"
qn:tabcolumns="[
{type:'string', name: 'Categories'},
{type:'number', name: 'Counts'}]"
qn:options="{
backgroundColor: '#F7F7F7'}"></div>
<p> {{tempGraph}}</p>
<p>{{tempGraph2}}</p>
Even using the ng-model, the graph is not being updated but the {{tempGraph2}} output is. Below is the content of the javascript.
Question: Do I need to create something to redraw the graph after I pull in new data or is there another set of logic I need to be using.
app.js:
$scope.tempGraph2 = [['Domain names','Domain Count'],
["placeholder",6],];
$scope.selectJobRow = function(rowIndex) {
$scope.selectedJobRow = rowIndex;
if ($scope.selectedJobRow > -1) {
$scope.showProgress();
$scope.input.job = $scope.input.jobList[rowIndex];
var prepFile = {fileName: $scope.input.job.outputFile, data: "test"}
$http.post("file/graph", prepFile)
.success(function(data, status) {
$scope.input.graphData = data;
$scope.tempGraph2 = $scope.input.graphData.data;
$scope.hideProgress();
$scope.tempGraph = [
['Domain names','Domain Count'],
["Positive-Female",123],
["Positive-GenderNeutral",22],
["Positive-Male",4],
["Neutral-Female",6],
["Neutral-GenderNeutral",76],
["Neutral-Male",8],
["Negative-Female",3],
["Negative-GenderNeutral",98],
["Negative-Male",19]
];
})
.error(function(data, status) {
$scope.hideProgress();
alert("Failed!!!!");
});
}
}
angular.module('charts.table', [
])
.directive('qnOptions', [
function() {
return {
require: '?ngModel',
link: function(scope, element, attr, controller) {
var settings = {
is3D: true
};
var getOptions = function() {
return angular.extend({ }, settings, scope.$eval(attr.qnOptions));
};
// creates instance of datatable and adds columns from settings
var getDataTable = function() {
var columns = scope.$eval(attr.qnTabcolumns);
var data = new google.visualization.DataTable();
angular.forEach(columns, function(column) {
data.addColumn(column.type, column.name);
});
return data;
};
var init = function() {
var options = getOptions();
if (controller) {
var drawChart = function() {
//var data = getDataTable();
// set model
// data.addRows(controller.$viewValue);
var data = new google.visualization.arrayToDataTable(controller.$viewValue);
/*var data = new google.visualization.arrayToDataTable([
['Move', 'Percentage'],
["Positive-Female",6],
["Positive-GenderNeutral",0],
["Positive-Male",17],
["Neutral-Female",6],
["Neutral-GenderNeutral",0],
["Neutral-Male",8],
["Negative-Female",3],
["Negative-GenderNeutral",0]
]); */
// Instantiate and draw our chart, passing in some options.
var chart = new google.visualization.Table(element[0]);
chart.draw(data);
};
controller.$render = function() {
drawChart();
};
}
if (controller) {
// Force a render to override
controller.$render();
}
};
// Watch for changes to the directives options
scope.$watch(getOptions, init, true);
scope.$watch(getDataTable, init, true);
}
};
}
]);
I can get the table to update from when I toggle between static data but not with dynamic data.
Related
Widget chart in aspnetzero jquery
I am trying to implement an apex pie chart in aspnetzero dashboard, when creating the widget everything works fine, but when I try to create the same widget I get the pie chart in the previous widget I created (Meaning I have two pie chart in one widget and then one empty widget, This is my implemented code below (function () { app.widgets.Widgets_Host_ErrorLogRate = function () { var _hostDashboardService = abp.services.app.hostDashboard; var _widgetBase = app.widgetBase.create(); const success = '#1BC5BD'; const danger = '#F64E60'; var _widget; var _$errorLogRateContainer; this.init = function (widgetManager) { _widget = widgetManager.getWidget(); _$errorLogRateContainer = _widget.find('.kt_chart_error_log_rate'); _widgetBase.runDelayed(getErrorLogRateData); }; var errorLogRate = function (data) { const apexChart = "#kt_chart_error_log_rate"; var options = { series: [data[0], data[1]], chart: { width: 350, type: 'pie', }, labels: [app.localize('Success'), app.localize('Fault')], responsive: [{ breakpoint: 480, options: { chart: { width: 200 }, legend: { position: 'bottom' } } }], colors: [success, danger] }; var chart = new ApexCharts(document.querySelector(apexChart), options); chart.render(); }; var getErrorLogRateData = function () { abp.ui.setBusy(_widget); _hostDashboardService.getErrorLogRate().done(function (result) { errorLogRate(result.errorLogRates); }) .always(function () { abp.ui.clearBusy(_widget); });; }; }; })(); [This is a screenshot of the output where it puts bot charts in the same widget/card][1] [1]: https://i.stack.imgur.com/aHzu3.png
Problem with variable scope in nested Backbone views
I have a parent view which contains a Backgrid view. In the parent view's initialize section I define a variable isWellSelected. The variable is toggled in the Backgrid column logic when a tickbox is checked. I am able to watch the variable toggled when a box is ticked and unticked. However, once an event fires the variable is no longer in scope for the event to see. I suspect I may need to pass the variable to the Backrgrid view but I am unsure how to do that correctly. Please advise. app.wellCollectionView = Backbone.View.extend({ template: _.template($('#wellTemplate').html()), initialize: function() { this.isWellSelected = false; // isWellSelected toggled to true when a tickbox is checked in the columns block. var columns = [...]; // instantiate collection var wellCollection = new app.wellCollection; // Set up a grid view to use the pageable collection var wellGrid = new Backgrid.Grid({ columns: columns, collection: wellCollection }); // Initialize the paginator var paginator = new Backgrid.Extension.Paginator({ collection: wellCollection }); // Render the template this.$el.html(this.template()); // Render the grid this.$el.append(wellGrid.render().el); this.$el.append(paginator.render().$el); wellCollection.fetch({reset: true}).then(function () {...}); }, events: { 'click #EvaluateWell': function(){ this.evalWell(event, this.isWellSelected); console.log("In events - isWellSelected: " + this.isWellSelected);} }, // More stuff } Constructive feedback welcome. Thanks! Adding a snippet for "columns" as per JT's request: var columns = [ { name: '', label: 'Select', cell: Backgrid.BooleanCell.extend({ events : { 'change': function(ev){ var $checkbox = $(ev.target); var $checkboxes = $('.backgrid input[type=checkbox]'); if($checkbox.is(':checked')) { $checkboxes.attr("disabled", true); this.isWellSelected = true; // Disable all checkboxes but this one $checkbox.removeAttr("disabled"); } else { // Enable all checkboxes again $checkboxes.removeAttr("disabled"); this.isWellSelected = false; } } } }) }, { name: "api", label: "API", editable: false, // Display only! cell: "string" }, { name: "company", label: "Operator", editable: false, // Display only! cell: "string" }];
DevExtreme / Knockout.js implement JSON as datasource
I'm new to JavaScript and REST, and I need to implement JSON as datasource to devextreme using knockout.js. My problem is, that I can fetch the json, but it is not added to the datasource. I used console.log() for testing and noticed that the json is correctly loaded, but the datasource is empty (see comments in code below). How can I achieve the usage of my json as datasource? Note: I used DevExtreme load JSON as datasource using knockout as base for getting my JSON-contents. I have a sample JSON-File looking like this: { "ID":"3", "content": { "ProdId":"000176491264", "ProdDesc":"Sample 1", "Type":"A", } } And my current viewmodel looks like this: MyApp.overview = function (params) { "use strict"; var getData = function () { var deferred = $.Deferred(); var xmlhttp = new XMLHttpRequest(), json; xmlhttp.onreadystatechange = function() { if(xmlhttp.readyState === 4 && xmlhttp.status === 200) { json = JSON.parse(xmlhttp.responseText); // prints needed content: console.log(json.content); deferred.resolve(json.content); } }; xmlhttp.open('GET', 'http://localhost:56253/test/3?format=json', true); xmlhttp.send(); return deferred.promise(); }; var viewModel = { overviewDatagridOptions: { dataSource: getData(), selection: { mode: "single" }, columns: [{ dataField: "ProdId", caption: "ID" }, { dataField: "ProdDesc", caption: "Description" }, { dataField: "Type", caption: "Type" }], rowAlternationEnabled: true }, // Returns {} console.log("Datasource: " + JSON.stringify(viewModel.overviewDatagridOptions.dataSource)); return viewModel; }; Edit: I changed my datasource to this: dataSource: { load: function (loadOptions) { var d = new $.Deferred(); var params = {}; //Getting filter options if (loadOptions.filter) { params.filter = JSON.stringify(loadOptions.filter); } //Getting sort options if (loadOptions.sort) { params.sort = JSON.stringify(loadOptions.sort); } //Getting dataField option if (loadOptions.dataField) { params.dataField = loadOptions.dataField; } //If the select expression is specified if (loadOptions.select) { params.select= JSON.stringify(loadOptions.select); } //Getting group options if (loadOptions.group) { params.group = JSON.stringify(loadOptions.group); } //skip and take are used for paging params.skip = loadOptions.skip; //A number of records that should be skipped params.take = loadOptions.take; //A number of records that should be taken var obj; $.getJSON('http://localhost:56253/test/3?format=json', params).done(function (data) { d.resolve(data); }); //return obj; return d.promise(); }, [...] Based on the demo found here: https://www.devexpress.com/Support/Center/Question/Details/KA18955 Now, the output from the datasource is no longer empty, and looks like this: Object - load:(loadOptions) - arguments:(...) - caller:(...) - length:1 - name:"load" - prototype:Object - __proto__:() - [[FunctionLocation]] - [[Scopes]]:Scopes[1] - totalCount:(loadOptions) - arguments:(...) - caller:(...) - length:1 - name:"totalCount" - prototype:Object - __proto__:() - [[FunctionLocation]] - [[Scopes]]:Scopes[1] - __proto__:Object
Kendo Grid Child -> using CRUD toolbar
My problem is that I Have Hierarchical grid (Master and Child) let say I Have a Department Grid it contains List of Employee Grid, and they both use same datasource. Here's my GridChild Code: function detailInit (e){ var msterRow = e.sender.items().index(e.masterRow).toString(); var grid = $("<div id='childGrid"+msterRow+"' class=childGrid'/>").appendTo(e.detailCell).kendoGrid({ data: e.data.DeptEmployees, schema: { model: { fields: { foo: {--skip--}, bar: {--skip--} } } }, toolbar: ["create", "cancel", "save"], editable: "popup", columns: [ --skip--] save: function(e){ ajaxUpdateDepartment(msterRow, this.dataSource.data()); } }) As you can see i use data: e.data.DeptEmployees, as child data source to fetch data. Now I'm stacked in how can I update the child data source? What I have Tried: I add child's dataSource.transport for updates, but my child grid keeps on loading. So I end up configuring the save: function (e) and simply send all data source of the current child but popup editor didn't close at all. And I'm having difficulty to refresh the child data source. I also attempt to convert my Master and Child Grid to ASP Razor but there was no definite example if how could I handle it in back end, and also my child grid contains drop down grid, so that would be a big re-do. And I also don't know if how can I pass customize parameter through it I am desperate, I can't find any working reference except this one. but it's using odata, and I dont have child id to use as reference, since I am only using list which I retrieve in a user event. Please help :'( I'm taking too much time for this one.
The solution is to define a transport properties, in order to fetch data from master, I only need to define the data and convert that to Jason. take a look of these code: function detailInit (e){ var msterRow = e.sender.items().index(e.masterRow).toString(); var grid = $("<div id='childGrid"+msterRow+"' class=childGrid'/>").appendTo(e.detailCell).kendoGrid({ //data: e.data.ChildDetails, transport: { read: function (o) { console.log("child read"); var data = e.data.ChildDetails.toJSON(); o.success(data); }, update: function (o) { console.log("child update"); var data = o.data, arentItem = findByID(data.id); for (var field in data) { if(!(field.indexOf("_") === 0)){ arentItem[field] = data[field]; } } e.data.dirty = true; saveChild(record, "#suffix", msterRow, "update"); o.success(); }, destroy: function (o) { var parentItem = findByID(o.data.id); preventBinding = true; e.data.ChildDetails.results.remove(parentItem); o.success(); saveChild(record, "#suffix", msterRow, "destroy"); }, create: function (o) { console.log("child create"); var record = o.data; record.id = index; index++; saveChild(record, "#suffix", msterRow, "create"); o.success(record); } }, schema: { model: { fields: { foo: {--skip--}, bar: {--skip--} } } }, toolbar: ["create", "cancel", "save"], editable: "popup", columns: [ --skip--] } Here's the working dojo snippet
how do you call getJSON inside the highchart section
Currently I am doing this: $(function () { // Create the chart $.getJSON('db_cpu.php', function(data) { var chart = new Highcharts.StockChart({ chart: { renderTo: 'container' }, rangeSelector: { enabled: false }, title: { text: 'Database utilization' }, series: data }, function (chart) { normalState = new Object(); normalState.stroke_width = null; normalState.stroke = null; normalState.fill = null; normalState.padding = null; //normalState.r = null; normalState.style = hash('text-decoration', 'underline'); hoverState = new Object(); hoverState = normalState; pressedState = new Object(); pressedState = normalState; //pressedState.style = hash('text-decoration', 'none'); chart_1DButton = chart.renderer.button('1D', 52, 10, function () { $.getJSON('db_memory.php', function (data) { console.log(data); chart.series[0].setData(data); chart.redraw(); }); unselectButtons(); chart_1DButton.setState(2); }, normalState, hoverState, pressedState); chart_1DButton.add(); }); function unselectButtons() { chart_1DButton.setState(0); } }); }); when I clicked on the button, my chart does not diplay any data. dp_cpu.php and db_memory.php outputs json formated data that has name and data in it already. For exmaple dp_cpu.php outputs this data: [{"name":"ServerA","data":[[1375142940000,1.85],[1375143540000,2.07],[1375144140000,1.96],[1375144740000,1.9],[1375145340000,2.06],[1375145940000,2.03],[1375146540000,1.69],[1375147140000,2.6],[1375147740000,2.1],[1375148340000,1.68],[1375148940000,2.03],[1375149540000,1.83],[1375150140000,1.84],[1375150740000,2.01],[1375151340000,1.88],[1375151940000,1.6],[1375152540000,2.02],[1375153140000,1.27],[1375153740000,1.47],[1375154340000,2],[1375154940000,1.97],[1375155540000,2.51],[1375156140000,3.59],[1375156740000,4.06],[1375157340000,4.13],[1375157940000,4.15],[1375158540000,4.19],[1375159140000,4.13],[1375159740000,4.44],[1375160340000,4.14],[1375160940000,4.15],[1375161540000,5.01],[1375162140000,4.13],[1375162740000,5],[1375163340000,4.97],[1375163940000,5.04],[1375164540000,5.09],[1375165140000,5.14],[1375165740000,4.93],[1375166340000,4.43],[1375166940000,5],[1375167540000,4.93],[1375168140000,5.1],[1375168740000,5.05],[1375169340000,5],[1375169940000,5.12],[1375170540000,4.14],[1375171140000,4.13],[1375171740000,4.85],[1375172340000,4.19],[1375172940000,4.13],[1375173540000,4.17],[1375174140000,2.02],[1375174740000,1.62],[1375175340000,1.77],[1375175940000,2.01],[1375176540000,1.86],[1375177140000,1.85],[1375177740000,2.1],[1375178340000,2.03],[1375178940000,1.79],[1375179540000,2.09],[1375180140000,1.95],[1375180740000,1.73],[1375181340000,2.12],[1375181940000,2.07],[1375182540000,1.65],[1375183140000,2.1],[1375183740000,2.03],[1375184340000,1.63],[1375184940000,2.13],[1375185540000,1.93],[1375186140000,1.65],[1375186740000,2.19],[1375187340000,1.98],[1375187940000,1.69],[1375188540000,2.13],[1375189140000,1.93],[1375189740000,1.72],[1375190340000,2.15],[1375190940000,2.07],[1375191540000,1.7],[1375192140000,2.15],[1375192740000,2.03],[1375193340000,1.73],[1375193940000,2.71],[1375194540000,1.96],[1375195140000,1.72],[1375195740000,2.15],[1375196340000,2.15],[1375196940000,1.85],[1375197540000,2.2],[1375198140000,1.93],[1375198740000,1.8],[1375199340000,2.19],[1375199940000,1.98],[1375200540000,1.85],[1375201140000,2.27]]}] I have some more info. when I do another getJSON as below example, It looks like I need to reset each series. This is really not convenient. I need to be able to read and external file and just show whatever in that file as chart and redraw the chart. Any ideas? $.getJSON('db_memory.php', function (data) { console.log(data); chart.series[0].setData([[1375142940000,100],[1375143540000,2.07],[1375144140000,1.96],[1375144740000,1.9],[1376408000000,90.06]]); chart.series[1].setData([[1375142940000,10],[1375143540000,20.07],[1375144140000,40.96],[1375144740000,50.9],[1376408000000,50.06]]); chart.series[2].setData([[1375142940000,10],[1375143540000,20.07],[1375144140000,40.96],[1375144740000,50.9],[1376408000000,20.06]]); chart.series[3].setData([[1375142940000,10],[1375143540000,20.07],[1375144140000,40.96],[1375144740000,50.9],[1375145340000,10.06]]); }); I have tried something like this and it is partially working with one problem. After clicking the button, I get the chart but my button disappears: $(function () { // Create the chart $.getJSON('db_pc.php', function(data) { var chart = new Highcharts.StockChart({ chart: { renderTo: 'container' }, rangeSelector: { enabled: false }, title: { text: 'Database utilization' }, series: data }, function (chart) { normalState = new Object(); normalState.stroke_width = null; normalState.stroke = null; normalState.fill = null; normalState.padding = null; //normalState.r = null; normalState.style = hash('text-decoration', 'underline'); hoverState = new Object(); hoverState = normalState; pressedState = new Object(); pressedState = normalState; //pressedState.style = hash('text-decoration', 'none'); chart_1DButton = chart.renderer.button('1D', 52, 10, function () { $.getJSON('db_memory.php', function (data1) { var chart = new Highcharts.StockChart({ chart: { renderTo: 'container' }, rangeSelector: { enabled: false }, title: { text: 'Database utilization' }, series: data1 }); }); unselectButtons(); chart_1DButton.setState(2); }, normalState, hoverState, pressedState); chart_1DButton.add(); }); function unselectButtons() { chart_1DButton.setState(0); } }); });
You can use addSeries() then you will not need to reset data, but in case when you use setData, redrawing is called, so redraw() can be skipped.
You only add your button when the chart is created. The problem is that when you use the following code , new Highcharts.StockChart..., the chart will load again, so it's will render without your button. So, you have two options, add a callback that will add the button again, or use serie.setData to change it's data dinamically. I'd go with the second option. Other problem is that the response is an array, you have to access it the following way data[0] Finally will have the following code: chart_1DButton = chart.renderer.button('1D', 52, 10, function () { $.getJSON('db_memory.php', function (data) { // update data // chart.series[0].setData( data[0].data ); // update series' options chart.series[0].update(data[0]); }); unselectButtons(); chart_1DButton.setState(2); }, normalState, hoverState, pressedState);
after looking at different options, I realized that what I need to do maybe better implemented using html/css type buttons: https://gist.github.com/kix/3039177 And using jquery click event I can load any kind of chart to the div: $(document).ready(function(){ $("#prof_d").click(function(){ web_cpu(); }); });