How to get data event click in angular google chart-angular 2+ - angular6

I used the google charts in my angular project dashboard.
By reading the document: https://github.com/FERNman/angular-google-charts , I used the below code for getting the event(which should contain the elements of the chart which I selected)
As per the document, the select event is emitted when an element in the chart gets selected.
<google-chart (select)="onSelect($event)"></google-chart>
I used the same in my code.
Html:`
<google-chart #chart [title]="Bartitle" [type]="Bartype" [data]="Bardata" [columnNames]="BarcolumnNames"
[options]="Baroptions" [width]="Barwidth" [height]="Barheight"
(select)="onSelect($event)">
</google-chart>`
Component.Ts
this.Bartitle = 'Current and Target';
this.Bartype = 'BarChart';
this.Bardata = [
["2012", 900, 390],
["2013", 1000, 400],
["2014", 1170, 440],
["2015", 1250, 480],
["2016", 1530, 540]
];
this.BarcolumnNames = ["Year", "Current", "Target"];
this.Baroptions = {
hAxis: {
title: 'Maturity'
},
vAxis: {
title: 'Month'
},
};
this.Barwidth = 200;
this.Barheight = 200;
onSelect(event) {
console.log(event);
}
But I dont get the values which I selected..
I need the values of maturity and the year... How i get that?? Did I made any changes??

Select
The select event is emitted when an element in the chart gets selected.
<google-chart (select)="onSelect($event)"></google-chart>
The event of type ChartSelectionChangedEvent containing an array of selected values.
in component
EDIT : Based on comments
onSelect(event) {
const { row, column } = event[0];
const year = this.Bardata[row][0];
let selectedItem;
if (column === 1) {
selectedItem = "current";
}
if (column === 2) {
selectedItem = "target";
}
console.log("year", year, "SelectedItem" ,selectedItem, this.Bardata[row][column]);
}
for more info read the documentation :
https://github.com/FERNman/angular-google-charts

Related

ag-Grid - Is it possible to create a floating menu for each row?

I'm trying to create a menu that appears when a user hovers on a row, just like in the image below.
I did not find any built-in option to achieve this. Also tried using a custom CellRenderer function to create an element that I could move around later, but that didn't work as expected since it presented some other challenges (css wise) and was not really achieving the goal.
Is there a way to build this kind of menus in ag-Grid?
To work around the problem, you could use onCellMouseOver & onCellMouseOut methods:
var gridOptions = {
columnDefs: columnDefs,
onCellMouseOver : onCellMouseOver,
onCellMouseOut: onCellMouseOut,
...
};
Define both functions:
var onCellMouseOver = function(event){
//Get current row
var rowIndex = event.node.rowIndex;
var row = gridOptions.api.getDisplayedRowAtIndex(rowIndex);
//Set current row as not selected - in order to base on 'cellStyle' function
row.setSelected(true);
//Setup refresh params
var params = {
force: true, //Force refresh as cell value didn't change
rowNodes: [row]
};
//Refresh current row cells
gridOptions.api.refreshCells(params);
}
var onCellMouseOut = function(event){
//Get current row
var rowIndex = event.node.rowIndex;
var row = gridOptions.api.getDisplayedRowAtIndex(rowIndex);
//Set current row as not selected - in order to base on 'cellStyle' function
row.setSelected(false);
//Setup refresh params
var params = {
force: true, //Force refresh as cell value didn't change
rowNodes: [row]
};
Then define 'cellStyle' function for your column:
var columnDefs = [
{headerName: "your_column_name", field: "your_column",
cellStyle: function(params) {;
console.log('Is row selected', params.node.selected);
if (params.node.selected) {
return {display : 'none'};
} else {
return {display : 'inherit'};
}
}
}
];
You can find more about data refresh here: https://www.ag-grid.com/javascript-grid-refresh/
The full implementation of the code above might be found here: Working example
Second solution, edited after comments:
Another way is to use css classes to achieve the result.
{
headerName: "Price",
field: "price",
cellStyle: { "text-align": "center" },
cellRenderer: function(params) {
return (
"<div class='buttons'>" +
"<div class='back'>" +
params.value +
"</div>" +
"<div class='front'><button>Option A</button><button>Option B</button></div>" +
"</div>"
);
}
Buttons are shown on hover based on .ag-row-hover ag-grid class:
.front {
display: none;
}
.ag-row-hover .front {
display: inherit;
}
Working example

Google column chart showing incorrect date

I am working on google column chart. I have created 3 columns while generating charts. Here are those columns.
var dtblData = new google.visualization.DataTable();
dtblData.addColumn('string', 'Names');
dtblData.addColumn('datetime', 'Intime');
dtblData.addColumn('datetime', 'Outtime');
I am using following data to show on graph.
[{"display_name":"Aditi Badurkar
","in_time":{"year":2017,"month":6,"day":22,"hours":11,"minutes":7,"seconds":8,"miliseconds":470},"out_time":{"year":2017,"month":6,"day":22,"hours":12,"minutes":45,"seconds":44,"miliseconds":237}}]
Here is my code :-
google.charts.load('current', { 'packages': ['corechart', 'bar'] });
google.charts.setOnLoadCallback(drawStuff);
function drawStuff() {
var chartDiv = document.getElementById('chart_div');
var dtblData = new google.visualization.DataTable();
dtblData.addColumn('string', 'Names');
dtblData.addColumn('datetime', 'Intime');
dtblData.addColumn('datetime', 'Outtime');
for (var i = 0; i < data.length; i++) {
if (data[i].out_time.year == 0) {
dtblData.addRow([data[i].display_name, new Date(data[i].in_time.year, data[i].in_time.month, data[i].in_time.day, data[i].in_time.hours, data[i].in_time.minutes, data[i].in_time.seconds, data[i].in_time.miliseconds), null]);
}
else {
dtblData.addRow([data[i].display_name, new Date(data[i].in_time.year, data[i].in_time.month, data[i].in_time.day, data[i].in_time.hours, data[i].in_time.minutes, data[i].in_time.seconds, data[i].in_time.miliseconds), new Date(data[i].out_time.year, data[i].out_time.month, data[i].out_time.day, data[i].out_time.hours, data[i].out_time.minutes, data[i].out_time.seconds, data[i].out_time.miliseconds)]);
}
}
var dateinFormat = new google.visualization.DateFormat({ formatType: 'long', pattern: "dd/MM/yyyy HH:mm:ss ZZZZ" });
dateinFormat.format(dtblData, 1);
var dateOutFormat = new google.visualization.DateFormat({ formatType: 'long', pattern: "dd/MM/yyyy HH:mm:ss ZZZZ" });
dateOutFormat.format(dtblData, 2);
var materialOptions = {
//width: 900,
chart: {
title: '',
subtitle: 'Intime, Outime of your kids or staff'
},
series: {
0: { axis: 'In Time' }, // Bind series 0 to an axis named 'In Time'.
1: { axis: 'Out time' } // Bind series 1 to an axis named 'Out Time'.
},
axes: {
y: {
distance: { label: 'In Time' }, // Left y-axis.
brightness: { side: 'right', label: 'Out Time' }, // Right y-axis.
}
},
};
function drawMaterialChart() {
var materialChart = new google.charts.Bar(chartDiv);
materialChart.draw(dtblData, google.charts.Bar.convertOptions(materialOptions));
}
drawMaterialChart();
}
My problem is, on graph it is showing month as July but in data it is June. I am not getting why it is showing wrong month when I scroll mouse pointer on bar? Can someone help me to solve this? I think it might be time zone issue.
Please see screenshot.
The Month in JavaScript is Zero Based, so ranges from 0 to 11 (0 meaning January and 11 meaning December).
For your code, you may decrement the month value by 1 to solve this.
Something that may be useful:
Why does the month argument range from 0 to 11 in JavaScript's Date constructor?

Flare ItemVisualisation

Using the latest Flare build originally built by prefuse, I am trying to get an indent field like the one in Layouts seen here. I am working with a list of objects that I pull from Google Firebase. While I can put them on a graph just fine and compare one and other values I can't find instructions on the different layouts. I am about to study the docs but I wanted to know if there was anything else out there I could reference.
Edit:
http://flare.prefuse.org/api/flare/vis/operator/layout/Layout.html I have found the general layouts here. However I only am able to show 1 or two circles unless I do AxisLayout.
For reference, my data pulled from firebase is something like this.
An array of objects.
Each object has properties name, sales, date, active and such.
I want it to act like the example above and show the item name in each circle. Then when the user clicks the circle he is able to show the properties of the item.
Edit: I was able to find an article on it, but after hours of constructing my data around his set format, I am not able to mock it entirely.
http://simon.oconnorlamb.com/ria/2012/03/visualising-data-with-flare/
Edit: To go into detail:
When I pull from my json list from Google Firebase I parse it so that it puts the items in referencable categories. All of which go into an array to mock the tutorial I linked above. I am trying to mock the structure as close as possible.
private function handleDataRead(e:DatabaseEvent):void
{
var trueDataArray:Array = new Array();
//Extract manufacturers.
var manufacturers:Vector.<String> = new Vector.<String>();
for each (var item:Object in e.data)
{
if (manufacturers.indexOf(item.Manufacturer) == -1)
{
manufacturers.push(item.Manufacturer);
//Example: {type:'Manufacturer',id:'0',name:'Company A'}
trueDataArray.push( {type:'manufacturer',
id:manufacturers.indexOf(item.Manufacturer).toString(),
name:item.Manufacturer});
}
}
//Extract Item Name
var itemNames:Vector.<String> = new Vector.<String>();
for each (var item:Object in e.data)
{
if (itemNames.indexOf(item.ItemName) == -1)
{
itemNames.push(item.ItemName);
var idValue:String = new String(itemNames.indexOf(item.ItemName) + (manufacturers.length - 1) +1);
trueDataArray.push( {type:'item',
id:idValue,
name:item.ItemName,
manufacturer:manufacturers.indexOf(item.Manufacturer).toString()} );
}
}
//Extract property 1
var mlCount:Vector.<int> = new Vector.<int>();
for each (var item:Object in e.data)
{
if (item.hasOwnProperty("ML"))
{
if (mlCount.indexOf(item.ML) == -1)
{
mlCount.push(item.ML);
var idValue:String = new String(mlCount.indexOf(item.ML) + (itemNames.length - 1) + (manufacturers.length - 1) +1);
trueDataArray.push({type:'mL',
id:idValue,
name:(item.ML as int).toString(),
item:itemNames.indexOf(item.ItemName).toString()});
}
}
}
//Extract another property
var mgCount:Vector.<int> = new Vector.<int>();
for each (var item:Object in e.data)
{
if (item.hasOwnProperty("MG"))
{
if (mgCount.indexOf(item.MG) == -1)
{
mgCount.push(item.MG);
var idValue:String = new String(mgCount.indexOf(item.MG) + mlCount.indexOf(item.ML) + (itemNames.length - 1) + (manufacturers.length - 1) +1);
trueDataArray.push({type:'mG',
id:idValue,
name:(item.MG as int).toString(),
mL:mlCount.indexOf(item.ML).toString()});
}
}
}
The result looks like this.
[
{
"name":"Company A",
"type":"manufacturer",
"id":"0"
},
{
"name":"Company B",
"type":"manufacturer",
"id":"1"
},
{
"name":"Company C",
"type":"manufacturer",
"id":"2"
},
{
"name":"Company D",
"type":"manufacturer",
"id":"3"
},
{
"name":"Company E",
"type":"manufacturer",
"id":"4"
},
{
"type":"manufacturer",
"id":"5"
},
... //So on
{
"manufacturer":"0",
"name":"Item Name 1",
"type":"item",
"id":"18"
},
{
"manufacturer":"0",
"name":"Item Name 2",
"type":"item",
"id":"19"
},
{
"manufacturer":"0",
"name":"Item Name 3",
"type":"item",
"id":"20"
},
{
"manufacturer":"0",
"name":"Item Name 4",
"type":"item",
"id":"21"
...//So on
{
"name":"60",
"item":"0",
"type":"mL",
"id":"195"
},
{
"name":"100",
"item":"5",
"type":"mL",
"id":"196"
},
{
"name":"120",
"item":"36",
"type":"mL",
"id":"197"
},
{
"name":"30",
"item":"100",
"type":"mL",
"id":"198"
}
...//and so forth
]
When I pass this to my function to create the nodes and edges (that I again based off the blog in the link above)
public function buildTree(arr:Array):Data
{
var d:Data = new Data(true);
//Keyed lookup for easy edge addition in step 2
var nodeLookup:Object = {};
var row:Object;
var ns:NodeSprite;
//Step 1: Add all rows of data;
for each(row in arr){
ns = d.addNode(row);
nodeLookup[row.id] = ns;
}
//Step 2: Add edges
for each(ns in d.nodes){
if(ns.data.hasOwnProperty('manufacturer')){
d.addEdgeFor(nodeLookup[ns.data.manufacturer],ns);
}
else if(ns.data.hasOwnProperty('item')){
d.addEdgeFor(nodeLookup[ns.data.item],ns);
}
else if(ns.data.hasOwnProperty('mL')){
d.addEdgeFor(nodeLookup[ns.data.mL],ns);
}
}
return d;
}
and construct it
data = buildTree(trueDataArray);
sourceTree = new ItemVisualisation(data);
sourceTree.bounds = new Rectangle(10, 10, 550, 550);
sourceTree.x = 20;
sourceTree.y = 20;
addChild(sourceTree);
sourceTree.operators.add(new IndentedTreeLayout());
sourceTree.operators.add(new ShapeEncoder("data.type"));
sourceTree.operators.add(new ColorEncoder("data.type", Data.NODES, "lineColor", ScaleType.CATEGORIES));
sourceTree.data.nodes.setProperties({fillColor:0, lineWidth:2});
sourceTree.update();
I get the following..
I almost have this down but I don't know what I am doing wrong. Everything seems to be as it should in relation.
Edit: It seems that the nodes may be linking properly with each other however this is not the layout I desire. I cannot get any other layouts to work either.
trueDataArray.push({type:'root', id:0, name:'rootname'});
I was able to solve this problem by binding everything to 1 node. I was having some trouble listing anything beyond two steps but that is beyond the requirement of my project.

Google Visualization Column Chart set a data column from query as role: "Style"

I have a Google Visualization Column Chart from a query that works fine. I can set the a columns with a style role after the query by using the code snippet below. It adds a new column to the query data and sets the role as "Style". This colors each of the column chart bars accordingly. But I want to be able to use one of my query columns "C" for example as the color code and not have to add it afterward. I can't seem to get this to work. Any ideas? I posted more of my code below the snippet so you can see where I'm coming from. Thanks so much guys for any help you can give. Brandon
var data = response.getDataTable();
data.addColumn({type: "string", role: "style" });
data.setCell(0,2,'red');
data.setCell(1,2,'orange');
data.setCell(2,2,'green');
data.setCell(3,2,'yellow');
// More code above this, but I ommited it.
function drawDashboard() {
var query = new google.visualization.Query(
'URL');
query.setQuery('SELECT A, B, C');
query.send(handleQueryResponse);
}
function handleQueryResponse(response) {
if (response.isError()) {
alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
var data = response.getDataTable();
data.addColumn({type: "string", role: "style" });
data.setCell(0,2,'red');
data.setCell(1,2,'orange');
data.setCell(2,2,'green');
data.setCell(3,2,'yellow');
// Create a dashboard.
var dashboard = new google.visualization.Dashboard(
document.getElementById('dashboard_div'));
// Create a range slider, passing some options
var scoreSlider = new google.visualization.ControlWrapper({
controlType: 'NumberRangeFilter',
containerId: 'filter_div',
options: {
filterColumnLabel: 'Class AVG'
}
});
var ClassFilter = new google.visualization.ControlWrapper({
controlType: 'CategoryFilter',
containerId: 'Classfilter_div',
options: {
'filterColumnLabel': 'Teacher Name','ui': { 'labelStacking': 'veClasscal','allowTyping': true,'allowMultiple': true
}
}});
// Create a Column Bar chart, passing some options
var columnChart = new google.visualization.ChartWrapper({
chartType: 'ColumnChart',
containerId: 'chart_div',
options: {
title: 'Math Proficiency by Class',
height: 320,
width: 500,
chartArea:{left:"10%",top:"10%",width:"80%",height:"60%"},
hAxis: {textStyle: {fontSize:14}, title: 'Teacher Name', titleTextStyle: {fontSize:14}, textStyle: {fontSize:14}},
vAxis: {minValue: 0, maxValue: 100, title: 'Math Proficiency AVG', titleTextStyle: {fontSize:14}, textStyle: {fontSize:14}},
legend: {position: 'none'},
animation: {duration:1500, easing:'out'},
colors: ['#a4c2f4','#3c78d8']
},
view: {columns: [0, 1, 2]}
});
// Define a table
var table = new google.visualization.ChartWrapper({
chartType: 'Table',
dataTable: data,
containerId: 'table_div',
options: {
width: '400px'
},
view: {columns: [0, 1,]}
});
// Establish dependencies, declaring that 'filter' drives 'ColumnChart',
// so that the column chart will only display entries that are let through
// given the chosen slider range.
dashboard.bind([scoreSlider], [table, columnChart]);
dashboard.bind([ClassFilter], [table, columnChart]);
// Draw the dashboard.
dashboard.draw(data);
}// More code below this, but I ommited it.
I'm not sure how you would add this to a column in the query but...
using a DataView with a calculated column should work...
Assumes the value you want to test is in the second column -- index 1
var data = response.getDataTable();
var view = new google.visualization.DataView(data);
view.setColumns([0, 1, {
type: "string",
role: "style",
calc: function (dataTable, rowIndex) {
if (dataTable.getValue(rowIndex, 1) < 0.69) {
return 'color: red;';
} else if ((dataTable.getValue(rowIndex, 1) >= 0.69) && (dataTable.getValue(rowIndex, 1) <= 0.79)) {
return 'color: yellow;';
} else {
return 'color: green;';
}
}
}]);

How to disable the Default sorting applied to groups in Kendo Grid

element.kendoGrid({
dataSource: {
data: scope.people,
group: {
field: "name"
}
},
groupable: true,
sortable: false,
pageable: {
refresh: true,
pageSizes: true
},
columns: scope.columns
});
Passed Data Source
$scope.people = [man1, man2, man3, man4];
var man1 = new Man('Test name2', 25);
var man2 = new Man('Test name1', 28);
var man3 = new Man('Test name1', 21);
var man4 = new Man('Test name3', 21);
Actual REsult :
Group are displaying in following order
First Name : Test name 1
First Name : Test name 2
First Name : Test name 3
Expected Result :
Group should display in following order
First Name : Test name 2
First Name : Test name 1
First Name : Test name 3
How do we achieve this?
By default groups are getting displayed in ascending order. But I want the order of group as it is there in the DataSource
If you can add your data through Ajax, then it's not too hard. I haven't found a way to do it without ajax though.
Your ajax would look like this:
$.ajax({
...[add your data call info here]...
}).done(function(result) {
var data = result.d.results; //this may be different for others
var sortNum = 1;
var lastVal;
for (var i = 0; i < data.length; i++) {
var val = data[i]["Firstname"];
if (!lastVal) {
lastVal = val;
}
if (val !== lastVal) {
sortNum++;
lastVal = val;
}
data[i]["SortOrder"] = sortNum;
}
});
This is if you just want to pass the data as is into your kendo grid.
Now that you have a sort column, tell kendo to group on that new column and replace the text with the original group column to display the names correctly.
//fetch FirstName value and return it to display instead of SortOrder value
function getHeader(val) {
var $data = $('.grid').data('kendoGrid').dataSource.data();
for (var i = 0; i < $data.length; i++) {
if ($data[i].SortOrder === val.value) {
return data[i].FirstName + '';
}
}
}
$('.grid').kendoGrid({
//... do all your normal kendo initialization, I'll just add the stuff you need to change
dataSource: {
schema: {
model: {
fields: { //add the new SortOrder column
SortOrder: {
type: 'number'
}
}
}
},
group: {
field: "SortOrder"
}
},
columns: [{ //add the new SortOrder column, but call the getHeader function to override the value displayed
field: "SortOrder",
hidden: true,
groupHeaderTemplate: getHeader
}]
});
That should be all you need to do. Hope this helps.