Why are more columns on one labels in Angular ChartJS? - javascript

I would like to create bar chart in Chart.js and shows which is the longest movie by category.
So I have a map which contain the title and length of the longest movie by category.
example:
0: {"Intouchables" => "107"} (from comedy)
1: {"The Devil's Advocate" => "144"} (from thriller)
I put these two data separately in an array:
this.keys = Array.from(this.map.keys());
this.values = Array.from(this.map.values());
In bar chart I want title as label, length as data and category as labels.
I tried this:
createDiagram(){
this. barChartOptions = {
scaleShowVerticalLines: false,
responsive: true
};
this.barChartLabels = ['Comedy', 'Thriller'];
this. barChartType = 'bar';
this. barChartLegend = true;
this.barChartData = [
{data: [this.values[0]], label: this.keys[0]},
{data: [this.values[1]], label: this.keys[1]}
];
}
html code:
<button (click)="createDiagram()">Create</button>
<div>
<div style="display: block">
<canvas baseChart
[datasets]="barChartData"
[labels]="barChartLabels"
[options]="barChartOptions"
[legend]="barChartLegend"
[chartType]="barChartType"></canvas>
</div>
</div>
and I get this bar chart:
So why are both columns on a comedy?
How can I do blue come up on thriller ?

https://stackblitz.com/edit/angular-zbiufy
You have two categories. So for every input u need to add two values. Then for two color, U can make fist item's second value 0 and second item's first value 0 then u can get what u want.
this.barChartData = [
{data: [this.values[0],0], label: this.keys[0]},
{data: [0,this.values[1]], label: this.keys[1]}
];

Related

Chart.js - Uncaught TypeError: Object.defineProperty called on non-object for multiple charts

I want to render multiple charts with same class name.The div with same class name contains canvas object.Most of the options are same but a few are different.I want to send them via data attributes.Everything is okay but when i am going to select canvas element on dom-object, it comes :
Uncaught TypeError: Object.defineProperty called on non-object
I dont know why it's happening.
Below is the html code
<td
class ="crypt-marketcap-canvas"
data-charts ="[65,59,81,81,56,55,40,80,90]"
data-bg = "d3f0df"
data-border = "8cd8aa">
<canvas />
</td>
and js codes are
var charts = document.getElementsByClassName("crypt-marketcap-canvas");
for( let chart of charts ){
let data = chart.dataset.charts;
// console.log(chart.dataset.charts);
let bg = chart.dataset.bg;
let border = chart.dataset.border;
let canvas = chart.querySelector('canvas');
// console.log(canvas);
let ctx = canvas.getContext('2d');
console.log(ctx);
let lineChartData = {
labels : ["1","2","3","4","5","6","7","8","9"],
datasets : [
{
backgroundColor : '#' + bg,
borderColor : '#' + border,
data : data,
bezierCurve : true
}
]
}
new Chart(ctx, { //Error is showing on this line
type:"line",
data:lineChartData,
options:options
});
}
Your issue here is that data is a string "[65,59,81,81,56,55,40,80,90]" which Chart can't understand.
If you do a JSON.parse it would work:
let data = JSON.parse(chart.dataset.charts);
That converts the data back to an array which, I guess, is your intention.
var charts = document.getElementsByClassName("crypt-marketcap-canvas");
for( let chart of charts ){
let data = JSON.parse(chart.dataset.charts);
// console.log(chart.dataset.charts);
let bg = chart.dataset.bg;
let border = chart.dataset.border;
let canvas = chart.querySelector('canvas');
let ctx = canvas.getContext('2d');
let lineChartData = {
labels : ["1","2","3","4","5","6","7","8","9"],
datasets : [
{
backgroundColor : '#' + bg,
borderColor : '#' + border,
data : data,
bezierCurve : true
}
]
}
new Chart(ctx, { //Error is showing on this line
type:"line",
data:lineChartData,
options: {}
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.bundle.min.js"></script>
<table>
<tbody>
<tr>
<td
class ="crypt-marketcap-canvas"
data-charts ="[65,59,81,81,56,55,40,80,90]"
data-bg = "d3f0df"
data-border = "8cd8aa">
<canvas />
</td>
</tr>
</tbody>
</table>
Extra
If you have any control on how data-charts is being written to the DOM I'd say avoid [ and just would do something like this:
<td
class ="crypt-marketcap-canvas"
data-charts ="65,59,81,81,56,55,40,80,90"
data-bg = "d3f0df"
data-border = "8cd8aa">
<canvas />
</td>
Then on your script: let data = chart.dataset.charts.split(','); leading to the same result.
Reason I recommend this is because JSON.parse can throw exceptions if something odd happens so you'd have to wrap within a try/catch block.

Dynamically populating google column charts

I want to populate a dynamic column chart such that the rows as well the columns are dynamic.
Here is a sample json array that I want to transform:
{"location":"Chain","item_category":"A","delay":"681"},
{"location":"Chennai ","item_category":"A","delay":"286"},{"location":"Bawal","item_category":"A","delay":"339"},{"location":"Haridwar","item_category":"A","delay":"1256"},{"location":"Ludhiana","item_category":"A","delay":"1048"},{"location":"Bawal","item_category":"B","delay":"1"}
There are 3 parameters namely location, item_category and delay where:
Location represents columns. (Varies dynamically)
Delay range should be on Y-axis. (Varies dynamically)
On x-axis they are mapped with items.
So far, I'm able to fetch all the required data but unable to create a graph out of it. I have referred to various libraries such as Google-visualization, Pchart, JPGraph and many more.
Each time I freeze on populating the graph dynamically.
Here is a sample code for populating Google Column Chart:
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {'packages':['bar']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Item Category', 'Location 1', 'Location 2', 'Location 3,...'],
['item1', 1000, 400, 200,...delay value of location 'n'],
['item2', 1170, 460, 250,...],
['item3', 660, 1120, 300]...],
['item4', 1030, 540, 350]
.
.
]);
//I want to populate this data variable using PHP
var chart = new google.charts.Bar(document.getElementById('my_Chartid'));
chart.draw(data, google.charts.Bar.convertOptions(options));
}
These are the links I have referred. I want to populate this data variable in javascript dynamically.
Google column chart dashboard
https://developers.google.com/chart/interactive/docs/gallery/columnchart
first, need to convert json data to normal array
then use a data view to create a column for each category
then aggregate the data and draw the chart
google.charts.load('current', {
callback: function () {
var jsonData = [
{"location":"Chain","item_category":"A","delay":"681"},
{"location":"Chennai ","item_category":"A","delay":"286"},
{"location":"Bawal","item_category":"A","delay":"339"},
{"location":"Haridwar","item_category":"A","delay":"1256"},
{"location":"Ludhiana","item_category":"A","delay":"1048"},
{"location":"Bawal","item_category":"B","delay":"100"}
];
// load chart data
var chartData = [];
jsonData.forEach(function (row, rowIndex) {
// column headings
var columns = Object.keys(row);
if (rowIndex === 0) {
chartData.push(columns);
}
// row values
var chartRow = [];
columns.forEach(function (column, colIndex) {
var chartCell = row[column];
if (colIndex > 1) {
chartCell = parseFloat(chartCell);
}
chartRow.push(chartCell);
});
chartData.push(chartRow);
});
var data = google.visualization.arrayToDataTable(chartData);
// create data view
var view = new google.visualization.DataView(data);
// init column arrays
var aggColumns = [];
var viewColumns = [0];
// build view & agg column for each category
data.getDistinctValues(1).forEach(function (category, index) {
// add view column
viewColumns.push({
calc: function (dt, row) {
if (dt.getValue(row, 1) === category) {
return dt.getValue(row, 2);
}
return null;
},
label: category,
type: 'number'
});
// add agg column
aggColumns.push({
aggregation: google.visualization.data.sum,
column: index + 1,
label: category,
type: 'number'
});
});
// set view columns
view.setColumns(viewColumns);
// agg view
var group = google.visualization.data.group(
view,
[0],
aggColumns
);
var chart = new google.charts.Bar(document.getElementById('chart_div'));
// use group data to draw chart
chart.draw(group);
},
packages:['bar']
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>

How to look up a value in AngularJS and display data in HTML table

I currently am getting to sets of JSON data back from a restul GET call. The first response set is used to build a HTML table of data. One of those values is an numeric ID from a data table in the DB.
In the other set of JSON data is a set of the values that correspond to the numeric id value in the first data set.
I'm trying to look up a value in the second set, based on the numeric value in the first set.
I've been able to accomplish this using a tag and ng-options, but this particular column need to just be a static tag with a data value.
My tag looks like
<td><select id="basOrgs" class="form-control grid-input" ng-model-options="{updateOn: 'blur'}" ng-model="item.OrgUid" ng-options="org.OrganizationUid as org.OrganizationDisplay for org in Orgs"></select></td>
What I'm trying to accomplish is to use the model item.OrgUid to look up a value in the Orgs data set to display Orgs.OrganizationDisplay based on the item.OrgUid value.
I've experimented with ng-repeat without any success.
<td ng-model="item.OrgUid" ng-repeat="org in Orgs track by org.OrganizationUid">{{org.OrganizationDisplay}}</td>
The item model looks like{OrgUid: 123456, Active:'Y',StartDate'}
The Org model looks like '{OrgUid: 123456, OrgDisplay: 'The Name of the Org'}
What I would like to do is display the OrgDisplay value in the tag based on the item.OrgUid value.
Any help would be appreciated.
Thanks,
--Jim
Assuming you have $scope.orgs in your controller, how about
<td ng-model="item.OrgUid" ng-repeat="org in Orgs track by org.OrganizationUid">{{lookup[org.OrganizationUid].OrganizationDisplay}}</td>
I'll edit this to include the right lookup code, but this is the idea.
You could make a lookup object to facilitate this:
var lookup = {};
for (var i = 0, len = orgs.length; i < len; i++) {
lookup[array[i].OrganizationUid] = array[i];
}
Here is a working snippet that uses lookup between two "data sets".
var myApp = angular.module('myApp', []);
myApp.controller('myController',
function($scope) {
$scope.Orgs = [{
OrgUid: 1,
OrgDisplay: 'Org 1'
}, {
OrgUid: 2,
OrgDisplay: 'Org 2'
}, {
OrgUid: 3,
OrgDisplay: 'Org 3'
}];
$scope.Items = [{
OrgUid: 1,
Active: 'Y',
StartDate: "12/1/1984"
}, {
OrgUid: 2,
Active: 'Y',
StartDate: "12/1/1984"
}, {
OrgUid: 3,
Active: 'Y',
StartDate: "12/1/1984"
}];
$scope.lookup = {};
for (var i = 0, len = $scope.Orgs.length; i < len; i++) {
$scope.lookup[$scope.Orgs[i].OrgUid] = $scope.Orgs[i];
}
});
.item {
border:1px solid green;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<html ng-app="myApp" ng-controller="myController">
<body>
<span class="item" ng-model="item.OrgUid" ng-repeat="item in Items">{{lookup[item.OrgUid].OrgDisplay}}</td>
</body>
</html>

Calculation for a cell with values from a cell from another table

I am trying to recreate a excel like feel using HandsOnTable and RuleJS. I am able to put in formulas where the calculations use cell values from the same table but cannot find a way to compute with cells from different tables.
In my example(see http://jsfiddle.net/satyamallyaudipi/3sct2h8q/81/ , I have been trying to compute the value of a Addl Costs cell in lineItem1 Table from Customer $ Targets in "Target" Table as in
=0.5*(B$2 from Target table)
Here is my html
<div id="target_Table" ></div>
<div id="lineItem_Table" ></div>
Here is the relevant javascript code
$(document).ready(function () {
var targetContainer = document.getElementById('target_Table');
var lineItemContainer = document.getElementById('lineItem_Table');
var targetData = [
["","2016","2017","2018","2019","2020","2021","2022","2023","2024","2025","Total"],
["Customer $ Targets:",500000,600000,700000,800000,900000,1000000,1100000,1200000,1300000,1400000,0],
["Customer % Targets:",0.55,0.56,0.57,0.58,0.58,0.59,0.59,0.60,0.6,0.6,0]];
var lineItemData = [
["","Total","2016","2017","2018","2019","2020","2021","2022","2023","2024","2025"],
["Qty","=SUM(C2:L2)",1500,2400,3000,3000,2100,0,0,0,0,0],
["Addl Cost", "=0.005*B$2","=0.005*C$2", ="0.005*D$2", "=0.005*E$2", "=0.005*F$2", "=0.005*G$2", "=0.005*H$2", "=0.005*I$2", "=0.005*J$2", "=0.005*K$2","=0.005*:L$2"]];
^-I would like this to be targetData B column
var target = new Handsontable(targetContainer, {
data: targetData,
....
});
var lineItem1 = new Handsontable(lineItemContainer, {
data: lineItemData,
.....
});
Here is the full jsfiddle http://jsfiddle.net/satyamallyaudipi/3sct2h8q/81/. Is it even possible to do this with HandsOnTable?

How can I make an ng-repeat filter that inserts the corresponding html and {{expression}} for each object?

Basically,
I have an array.
Some properties of each object in the array are different.
When ng-repeat iterates through the array, with a filter it should decide what html code to use, to display the preferred properties of each object with its own div classes.
(function() {
var app = angular.module('Veggies',[]);
app.controller('ArrayController', function(){
this.Array = Array;
});
var Vegetebles = [
{Veg_name: 'Onion', price:2.95},
{Veg_Article_Title: 'Garlic in Italy', year:20-10-2011},
{Veg_name: 'Carrot', price:3.95},
{Veg_name:'Celery', price:2.95},
{Veg_Article_Title:'Lettuce Growing 101', year:20-10-2011},
{Veg_name:'Pepper', price:3.95}
];
})();
What I need to achieve is the following:
Where if the object has a "Veg_Article_Title" key somewhere in it, then it is an article and should use the corresponding html code with its own div classes, that way it can be styled differently than an object that has a key of "Veg_name" and is a vegetable.
I tried doing this:
$scope.filter = function(Array){
angular.forEach(Array,function(value, key){
if (key === Veg_Article_Title){
$scope.myHTML =
"<div class = "Article_Title"><h1>{{Object.Veg_Article_Title}}</h1></div>"
"<div class = "Article_Year"><h2>{{Object.year}}</h2></div>";
}else (key === Veg_name){
$scope.myHTML =
"<div class = "Vegeteble"><h1>{{Object.Veg_name}}</h1></div>"
"<div class = "Vegeteble_Price"><h2>{{Object.price}}</h2></div>";
};
}
I'm really not sure if I am approaching this problem right and couldn't find anything similar.
I am relatively new to coding, so please excuse any syntax errors.
Many Thanks in Advance!
Please iterate your array using ng-repeat directive.
HTML Code:
<div ng-repeat="d in Vegetebles">
<div ng-if="d.Veg_name">Veg Name : {{d.Veg_name}}</div> <!--Put your html if veg name found-->
<div ng-if="d.Veg_Article_Title">Article Name : {{d.Veg_Article_Title}}</div> <!--Put your html if veg article title found-->
</div>
JS Code inside controller:
$scope.Vegetebles = [
{ Veg_name: 'Onion', price: 2.95 },
{ Veg_Article_Title: 'Garlic in Italy', year: 20 - 10 - 2011 },
{ Veg_name: 'Carrot', price: 3.95 },
{ Veg_name: 'Celery', price: 2.95 },
{ Veg_Article_Title: 'Lettuce Growing 101', year: 20 - 10 - 2011 },
{ Veg_name: 'Pepper', price: 3.95 }
];

Categories