AnyChart - Column Chart: get values of one category summarized - anychart

I tried to get a small AnyChart chart working but have some problems with my data setup.
What I want to have is a way for users to filter data. Therefor, I have to provide all information necessary for filtering within the data set. In the chart, only top level category is used and should display a summarized value of all rows that the filter applies to.
Here comes the code:
<html>
<body>
<script src="https://cdn.anychart.com/releases/8.2.1/js/anychart-bundle.min.js"></script>
<select id='depFilter'><option value='*'>All</option><option value='Development'>Development</option><option value='Accounting'>Accounting</option><option value='Sales'>Sales</option></select><br>
<select id='genderFilter'><option value='*'>All</option><option value='female'>female</option><option value='male'>male</option></select><br>
<button onClick='filterChart()'>Filter</button><br>
<div id="container"></div>
<script language='JavaScript'>
anychart.onDocumentReady(function() {
// create line chart
var dataSet = anychart.data.set([
["US", "Development", "male", 20],
["US", "Development", "female", 3],
["US", "Accounting", "male", 1],
["US", "Accounting", "female", 4],
["US", "Sales", "male", 15],
["US", "Sales", "female", 16],
["CA", "Development", "male", 12],
["CA", "Development", "female", 25],
["CA", "Accounting", "male", 1],
["CA", "Accounting", "female", 8],
["CA", "Sales", "male", 30],
["CA", "Sales", "female", 18],
]);
chart = anychart.column();
baseMapping = dataSet.mapAs({'x': 0, 'dep': 1, 'gender': 2, 'value': 3});
series = chart.column();
filterChart();
chart.container('container');
chart.draw();
});
function filterChart() {
var filteredMapping = baseMapping.filter("dep", function(value) { return document.getElementById("depFilter").value == '*' || value == document.getElementById("depFilter").value; });
filteredMapping = filteredMapping.filter("gender", function(value) { return document.getElementById("genderFilter").value == '*' || value == document.getElementById("genderFilter").value; });
series.data(filteredMapping);
}
</script>
As you can see, for each country there are filters for department and gender. Value is the number of employees.
By now, the chart only displays the last recent data point for each region. What it should do is to display sum of all employees the filter applies to.
Example:
- when filtering for female accountants it should be 4 at US and 8 at CA
- when filtering only for accountants it should be 5 for US and 9 for CA
xMode() function didn't do the job as it doesn't summarize but only overlay.
Is there a way to get this working in AnyChart?
Thanks in advance and sorry if this question already has been answered, I didn't find a suitable answer when trying to search for it.

The Cartesian chart doesn't apply any aggregations to user's data. If there are several values for the same category (US or CA), the chart will show the latest value. The latest value overrides the previous ones.
To meet your requirements you should preprocess data before applying to the chart. It means that in filter function you should create new data set that includes aggregated values according to filtering conditions. For example, you want to show the total number of employees in "development". Then you should sum "male" and "female" of "development" in US and CA. Then resulting data set should look like this:
var dataSet = anychart.data.set([
["US", 23],
["CA", 37]
]);
And then apply this new data set to the chart. It can be done inside the filter function.

Related

Get Array Based on samecategoryname using anjularjs

I have a Array has given below. In this array some objects contain with Key catagoryName. For each seperate CategoryName i need to get the count where ReadDate is null.
QUESTIONS HIGHLIGHTED:
Push into Array based on each Category ( category names might be 'N' number ).
Get the each category count where ReadDate is null.
.controller('testController',function($scope,$rootScope){
$rootScope.messages = [
{
"IntMessageUserId": 9,
"ReadDate": null,
"MessageSubject": "HOLY CRAP ",
"MessageText": "blah blah blah",
"Priority": 1,
"PriorityDescription": "High",
"StartDate": "2017-01-19T00:00:00",
"EndDate": "2017-07-01T00:00:00",
"IntMessageCategoryId": 36,
"CategoryName": "a New Category By Dave",
"CategoryDescription": "Only a couple",
"ActiveSw": true
},
{
"IntMessageUserId": 110,
"ReadDate": "null",
"MessageSubject": "Test_chm2",
"MessageText": "Test_chm2",
"Priority": 2,
"PriorityDescription": "Urgent",
"StartDate": "2017-01-04T00:00:00",
"EndDate": "2017-06-02T00:00:00",
"IntMessageCategoryId": 39,
"CategoryName": "Alerts",
"CategoryDescription": "Alerts",
"ActiveSw": true
},
{
"IntMessageUserId": 117,
"ReadDate": "2017-05-05T06:35:00",
"MessageSubject": "Test_chm2",
"MessageText": "Test_chm2",
"Priority": 1,
"PriorityDescription": "High",
"StartDate": "2017-01-04T00:00:00",
"EndDate": "2017-06-02T00:00:00",
"IntMessageCategoryId": 39,
"CategoryName": "Alerts",
"CategoryDescription": "Alerts",
"ActiveSw": true
},
{
"IntMessageUserId": 113,
"ReadDate": "2017-05-03T08:48:00",
"MessageSubject": "Testing PSC",
"MessageText": "Psc note that displays until May 26",
"Priority": 1,
"PriorityDescription": "High",
"StartDate": "2017-04-24T09:31:00",
"EndDate": "2017-05-26T09:31:00",
"IntMessageCategoryId": 59,
"CategoryName": "Alerts PSC",
"CategoryDescription": "Alerts PSC",
"ActiveSw": true
},
{
"IntMessageUserId": 130,
"ReadDate": null,
"MessageSubject": "17/18 Parking Pass sale dates",
"MessageText": "Parking Passes will be available for purchase for the 17/18 school year for all current Juniors starting on June 1st. Sophomores may purchase passes starting on August 1st. Sales are in person only at the school district offices. You must fill out our parking permit form, Show your current drivers license, and proof of insurance. Passes will be sold for $50.00 for the school year. \r\n\r\n",
"Priority": 0,
"PriorityDescription": "Normal",
"StartDate": "2017-05-05T10:40:00",
"EndDate": "2017-06-01T10:39:00",
"IntMessageCategoryId": 67,
"CategoryName": "High School Students",
"CategoryDescription": "High School students",
"ActiveSw": true
},
{
"IntMessageUserId": 111,
"ReadDate": "2017-05-03T08:50:00",
"MessageSubject": "Summer Sports Camps",
"MessageText": "Our summer sports camps flyers will be sent home in the next week or 2. Please check them out and see if you would like to enroll your child in a sports camp program. We encourage them to try something new, or improve their skills in an existing sport. ",
"Priority": 0,
"PriorityDescription": "Normal",
"StartDate": "2017-03-21T00:00:00",
"EndDate": "2017-05-15T00:00:00",
"IntMessageCategoryId": 69,
"CategoryName": "Athletic Department Notifications ",
"CategoryDescription": "Athletic Department.",
"ActiveSw": false
},
{
"IntMessageUserId": 131,
"ReadDate": null,
"MessageSubject": "End of Year Lunch balances",
"MessageText": "As we come to the end of our school year, a reminder that unused lunch funds will roll over to next school year and be available next year in the lunch line. If you have a student who is graduating and has unused funds, please consider donating those funds to a student in need.. You can contact the Food Service department at 513-555-5555 and we will be happy to coordinate this. Refunds of unused lunch funds can be issued for any student who's balance is greater than $5.00 Please fill out a refund form at the school office and they will be processed by our accounting department. Refund checks will be mailed within 30 days of receiving your forms in the office. Have a great summer. ",
"Priority": 0,
"PriorityDescription": "Normal",
"StartDate": "2017-05-05T10:45:00",
"EndDate": "2017-06-09T10:45:00",
"IntMessageCategoryId": 80,
"CategoryName": "Nutrition Services",
"CategoryDescription": "Nutrition Services",
"ActiveSw": true
}
];
What i tried till.
angular.forEach($rootScope.messages,function(value, key){
$scope.checkUnreadMessages(value.CategoryName);
})
var mainArray = [];
$scope.call = function(){
angular.forEach(arr, function(value, key){
var subarr = [];
subarr[value] = [];
angular.forEach($rootScope.messages, function(v, k){
if(value == v.CategoryName){
subarr[value].push(v.ReadDate);
}
})
mainArray.push(subarr);
})
}
I generally don't like to use extra library for a simple job which can be easily done in pure javascript.
https://repl.it/Hk45/2
Here is a link to a javascript compiler where you can see a solution.
Notice that all the work is done by the very simple function :
function fillOrInitiate(category, element){
if(categories[category]){
categories[category].push(element);
} else {
categories[category] = [];
categories[category].push(element);
}
}
Then just iterate through your data.
EDIT : Take care of your data, sometimes ReadDate is null and sometimes it is "null". However I took care of that in my example in the function CountReadDateNull.
You should not be able to visualize the data directly by printing final tab, but it is here as you can see on the second console.log
Why you are not using Underscore.js
Need to Extract Array Based on Category Name.
_.where( $rootScope.messages, {CategoryName: "searching category name"});
Get the each category count where ReadDate is null.
_.where( $rootScope.messages, {ReadDate: null}).length;
1) Iterate through an array of messages and check the same category name and then pushing it into new array, before that you need to group it using category name as the key.
var groupCategory = {};
angular.forEach($rootScope.messages, function (oldVal, newVal) {
if (oldVal.CategoryName === newVal.CategoryName) {
if (angular.isDefined(groupCategory[newVal.CategoryName])) {
groupCategory[newVal.CategoryName].push(newVal);
} else {
groupCategory[newVal.CategoryName] = [newVal];
}
}
});
2) Then, you can count the category group by filter/checking if ReadDate is null
var cnt = 0;
angular.forEach(sameCategoryObj, function (val) {
if(val.ReadDate === null) {
cnt++;
}
});

AngularJS filtering using external JSON

I've been wondering for some long time, how can I filter something like this. Here is my situation:
I have one JSON table like this:
var cars = [{
"id": 1,
"brand": "Ford",
"model": "Focus",
"generation": "2.0TDCi",
"version": "hatchback, 3 drzwi",
"mileage": 100,},{
"id": 2,
"brand": "Volkswagen",
"model": "Golf",
"generation": "III",
"version": " 1.9 TDI, hatchback, 4 drzwi",
"mileage": 14,}];
And I'm using this kind of generating table using data from JSON:
<tr data-ng-repeat="car in cars" (...)
I've also have a dropdown with multiselection:
<div ng-dropdown-multiselect="" options="exampleBrand" selected-model="exampleBrandModel" extra-settings="exampleSettings"></div>
Things which are imported into this selector are from JSON file:
$scope.exampleBrand = [{id: 1, label: "Ford"}, {id: 2, label: "Ferrari"}, {id: 3, label:"Suzuki"},
{id: 4, label:"Fiat"}, {id: 5, label:"Aston Martin"}, {id: 6, label:"Opel"}];
The model of thing which are selected lands here:
$scope.exampleBrandModel = [];
For example if I select "Ford", the JSON file with model looks like this (checked with
{{ exampleBrandModel| json }}
):
[
{
"id": "Ford"
}
]
And my question is. How can I use angular's filter option to make it working?
I was using something like that which was not working:
<tr data-ng-repeat="car in cars |filter: {exampleBrandModel : id}">
I want to have situation like this:
At start I get whole table with cars listed in and then I select "Ford". Now every row in table without "Ford" word should be filtered out.
Do someone know how can I do that?

How to display time stamp as date in higcharts?

I am building an application where it gets the data from facebook api and the graph is generated using the HighCharts.
The graph is generated successfuly, but the date i get is in the time stamp format. How can i convert it to the actual date format.
Here is the code:
xAxis: {
type: 'datetime',
dateTimeLabelFormats: { // don't display the dummy year
month: '%e. %b',
year: '%b'
},
title: {
text: 'Date'
}
},
Data:
series: [{"data": [["2015-11-15T08:00:00+0000", 55], ["2015-11-16T08:00:00+0000", 45], ["2015-11-17T08:00:00+0000", 32], ["2015-11-18T08:00:00+0000", 54], ["2015-11-19T08:00:00+0000", 34], ["2015-11-20T08:00:00+0000", 1]], "name": "page_views"}, {"data": [["2015-11-15T08:00:00+0000", 23], ["2015-11-16T08:00:00+0000", 67], ["2015-11-17T08:00:00+0000", 54], ["2015-11-18T08:00:00+0000", 23], ["2015-11-19T08:00:00+0000", 64], ["2015-11-20T08:00:00+0000", 23]], "name": "page_stories"}, {"data": [["2015-11-15T08:00:00+0000", 23], ["2015-11-16T08:00:00+0000", 64], ["2015-11-17T08:00:00+0000", 34], ["2015-11-18T08:00:00+0000", 32], ["2015-11-19T08:00:00+0000", 43], ["2015-11-20T08:00:00+0000", 43]], "name": "page_fan_adds"}]
Here is the application in JSFiddle
I am not sure if we can fetch the date in any format from facebook API.
I had in the past converted the date in my code once i retrieve the same.
Below is what i had implemented with VB.NET.
DateVariable.ToString().Substring(0, 10)).ToString("dd MMM yyyy")
Hope this helps you.

AngularJS get length by filtering 3rd level property

I have been trying to get the count of items that have a specific text match for a specific field but I haven't had any luck.
The link below is the closest example I have been able to implement, but all I can get it to return is the total number of entries in the table.
Angular Count Filtered Data
When I insert {{data.length}} into the view, it returns the total number of entries.
But when I change it to query the sub-field as {{(data|filter:{team:'A'}).length}} or {{(data|filter:{custom_fields.team:'A'}).length}} it returns a 0.
[{
"id": 1,
"custom_fields": {
"team": ["A"]
}
},{
"id": 2,
"custom_fields": {
"team": ["B"]
},
},{
"id": 3,
"custom_fields": {
"team": ["A"]
}
}]
Any thoughts or suggestions?
You can do that by filtering nested objects:
{{(data|filter:{custom_fields: {team: ['A']} }).length}}
Demo.

How to find number of distinct values from a collection

Suppose I have a collection like:
{
"id": 1,
"name": "jonas",
},
{
"id": 2,
"name": "jonas",
},
{
"id":3,
"name": "smirk",
}
How do I get :
Number of distinct names, like in this case, 2
The distinct names, in this case, jonas and smirk ?
With some Backbone and Underscore magic, combining collection.pluck and _.uniq:
pluck collection.pluck(attribute)
Pluck an attribute from each model in the collection. Equivalent to calling map, and returning a single attribute from the iterator.
uniq _.uniq(array, [isSorted], [iterator])
Produces a duplicate-free version of the array, using === to test object equality.
[...]
var c = new Backbone.Collection([
{id: 1, name: "jonas"},
{id: 2, name: "jonas"},
{id: 3, name: "smirk"}
]);
var names = _.uniq(c.pluck('name'));
console.log(names.length);
console.log(names);
And a demo http://jsfiddle.net/nikoshr/PSFXg/

Resources