I am working on Timeline charts in angularjs google chart API.
From Timeline chart API i understood that only 4 columns are allowed and the other column would be a tooltip column.
I have a requirement where i am attaching the ID of that row along with the description and i want to pass that ID when the row is clicked but dont want to show on the label.
js code:
angular.module('myApp', ['googlechart'])
.controller('myController', function($scope,$timeout) {
var chart1 = {};
chart1.type = "Timeline";
chart1.displayed = false;
var container = document.getElementById('timeline')
chart1.data = {
"cols": [{
id: "month",
label: "Month",
type: "string"
}, {
id: "description",
label: "Description",
type: "string"
}, {
id: "start",
label: "start",
type: "date"
}, {
id: "end",
label: "end",
type: "date"
}],
"rows": [{
c: [{
v: "January"
}, {
v: "Jan text here -$# 1001".trim().split(' -$#')[0]
}, {
v: new Date(2018, 3, 1)
}, {
v:new Date(2018, 4, 12)
} ]
}, {
c: [{
v: "February"
}, {
v: "feb text here -$# 1002".trim().split(' -$#')[0]
}, {
v: new Date(2018,4, 1)
}, {
v: new Date(2018, 4, 15)
} ]
} , {
c: [{
v: "april"
}, {
v: "april text here -$# 1003".trim().split(' -$#')[0]
}, {
v: new Date(2018,5, 1)
}, {
v: new Date(2018, 7, 15)
} ]
} ]
};
chart1.options = {
timeline: {
showRowLabels: false,
},
};
$scope.seriesSelected = function(selectedItem) {
var rowValue = chart1.data.rows[selectedItem.row].c[1].v;
alert(rowValue);
}
$scope.myChart = chart1;
});
In the above js code, i am attaching the rowID like 1001,1002,.. to the description column (Jan text here -$# 1001".trim().split(' -$#')[0]), but using trim() because i should not show the ID on the screen. When clicked on the row
var rowValue = chart1.data.rows[selectedItem.row].c[1].v; i wanted to get the entire value as Jan text here -$# 1001 but it is not showing the ID values as shown in the demo link. Any inputs on how to pass the ID values (1001,1002..) appended in the description to the $scope.seriesSelected .
PS: Is it possible to include another column where i can assign the ID values(1001,1002..), but it should not be shown on the webpage/tooltip.
you can assign properties to each cell, row, or column...
c: [{
v: "January"
}, {
v: "Jan text here", p: {id: 1001}
},
...
and use data table methods to get / set...
dataTable.getProperty(rowIndex, columnIndex, name);
dataTable.setProperty(rowIndex, columnIndex, name, value);
or access the property directly from the json used as the data table...
chart1.data.rows[selectedItem.row].c[1].p.id
Related
This is the result I want to achieve
dataset: [
dataset: [
{
seriesname: "",
data: [
{
value: "123",
},
{
value: "123",
},
]
},
]
]
My problem right now is that the second dataset gets duplicated.
This is how I am setting it (val is an integer and allYears is an array of integers):
this.grphColumn.dataSource.dataset[0].dataset = this.allYears.map(el => {
return {
seriesname: "Planned",
data: [{value: val}, {value: val}]
}
});
How can I make it so the dataset doesn't get duplicated?
You have to map the values separately, if you dont want the seriesName to be Repeated..
const yearsMap = this.allYears.map((el) => { return { value: el } });
this.grphColumn.dataSource.dataset[0].dataset = {
seriesname: "Planned",
data: yearsMap
}
I wanted to break down paragraph based on it’s entityRanges.
So the actual paragraph looks like this,
{
type: 'paragraph',
depth: 1,
text: 'Do you have questions or comments and do you wish to contact ABC? Please visit our customer support page.',
entityRanges: [{
type: 'LINK',
offset: 83,
length: 16,
data: {
target: '_self',
url: '/index.htm'
}
}]
}
But my expected results should be like below,
{
type: 'paragraph',
depth: 1,
text: 'Do you have questions or comments and do you wish to contact ABC? Please visit our customer support page.',
entityRanges: [{
type: 'LINK',
offset: 83,
length: 16,
data: {
target: '_self',
url: '/index.htm'
}
}],
embbeded: [{
type: 'text',
text: 'Do you have questions or comments and do you wish to contact ABC? Please visit our '
}, {
type: 'link',
text: 'customer support',
data: {
target: '_self',
url: '/index.htm'
}
}, {
type: 'text',
text: 'page.'
}]
}
I wanted to break down the text into multiple parts based on it’s offset & length values.
As per the example, customer support is the offset value.
So it should breakdown in the below order
Do you have questions or comments and do you wish to contact ABC?
Please visit our
customer support
page.
All above parts needs to pushed to new object embbeded.
I hope that I understood you correctly:
const data = {
"text": "Do you have questions or comments and do you wish to contact ABC? Please visit our customer support page.",
"entityRanges": [{
"type": "LINK",
"offset": 83,
"length": 16,
"data": {
"target": "_self",
"url": "/index.htm"
}
},
{
"type": "LINK",
"offset": 7,
"length": 4,
"data": {
"target": "_self",
"url": "/index.htm"
}
}
]
};
function breakData(data) {
let {
entityRanges,
text
} = data;
const result = [];
let finalPart = '';
let index = 0;
entityRanges
.sort((a, b) => a.offset - b.offset)
.forEach((styleRange) => {
const {
offset,
length,
type,
data
} = styleRange;
const firstPart = text.substring(index, offset);
result.push({
type: 'text',
text: firstPart,
});
index = offset + length; // + 1;
const secondPart = text.substring(offset, index);
result.push({
type,
data,
text: secondPart,
});
finalPart = text.substring(index);
});
if (finalPart) {
result.push({
type: 'text',
text: finalPart,
});
}
data.embbeded = result;
return data;
}
const result = breakData(data);
document.body.innerHTML = '<pre>' + JSON.stringify(result, null, ' ') + '</pre>';
I am adding the Google column chart I Pasted some code from AGC to my page but why is it not generating the chart?
Bar.cshtml
<div google-chart chart="myChartObject" width:100%;"></div>
#section scripts{
<script src="~/Scripts/Charts/BarCharts.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-google-chart/0.1.0/ng-google-chart.js" type="text/javascript"></script>}
MyApp.cshtml
var app = angular.module('MyApp', [])
app.filter('ctime', function(){
return function(jsonDate){
var date = new Date(parseInt(jsonDate.substr(6)));
return date;
}
})
Javfile.Js
var app = angular.module("MyApp", ['googlechart']);
app.controller("GenericChartCtrl", function ($scope) {
$scope.myChartObject = {};
$scope.myChartObject.type = "ColumnChart";
$scope.onions = [
{ v: "Onions" },
{ v: 3 },
];
$scope.myChartObject.data = {
"cols": [
{ id: "t", label: "Topping", type: "string" },
{ id: "s", label: "Slices", type: "number" }
], "rows": [ {
c: [ { v: "Mushrooms" }, { v: 3 },]},{ c: $scope.onions },{c: [{ v: "Olives" }, { v: 31 }]}
<div google-chart chart="myChartObject" style="width:100%;" ng-controller="GenericChartCtrl">
</div>
Try this i hope it will work
I'm trying to display data in a stacked graph using kendo ui. Here is my code:
var data = [
// June
{ Start: "2014-06-01T00:00:00", Name : "Series 1", Value: 1 },
{ Start: "2014-06-01T00:00:00", Name : "Series 2", Value: 2 },
{ Start: "2014-06-01T00:00:00", Name : "Series 3", Value: 10 },
// July
{ Start: "2014-07-01T00:00:00", Name : "Series 1", Value: 2 },
{ Start: "2014-07-01T00:00:00", Name : "Series 2", Value: 2 },
{ Start: "2014-07-01T00:00:00", Name : "Series 3", Value: 2 },
// August
{ Start: "2014-08-01T00:00:00", Name : "Series 1", Value: 3 },
{ Start: "2014-08-01T00:00:00", Name : "Series 2", Value: 2 },
{ Start: "2014-08-01T00:00:00", Name : "Series 3", Value: 1 },
// September
{ Start: "2014-09-01T00:00:00", Name : "Series 2", Value: 2 },
{ Start: "2014-09-01T00:00:00", Name : "Series 3", Value: 3 },
// October
{ Start: "2014-10-01T00:00:00", Name : "Series 1", Value: 1 },
{ Start: "2014-10-01T00:00:00", Name : "Series 3", Value: 3 }
]
var stocksDataSource = new kendo.data.DataSource({
data: data,
group: {
field: "Name"
},
sort: [{ field: "Start", dir: "asc"} ]
});
function createChart() {
$("#chart").kendoChart({
dataSource: stocksDataSource,
series: [{
type: "column",
field: "Value",
name: "#= group.value #",
stack: true,
tooltip: {
template: "#=kendo.toString(new Date(category), 'd MMM yyyy')#<br/>" +
"#=dataItem.Name#<br/>"+
"Value: #=dataItem.Value#",
visible: true
},
}],
categoryAxis: {
field: "Start",
type: "date",
labels: {
format: "MMM"
}
}
});
}
$(document).ready(createChart);
$(document).bind("kendo:skinChange", createChart);
Note that September and October data do not have values for some series. This completely screws up the chart display in quite unexplainable way:
As you can see both September and October data do not match the json. It's especially weird with October data because three values are displayed whereas only 2 are given.
Here is JSFiddle: http://jsfiddle.net/12ob7qmx/6/
Are there any settings on the chart that I can set so it works, or will I have to loop through the dataset and fill in missing data with zero values?
The way I solved this issue is by looping through my data and adding missing values with 0's.
I don't think there is a better way, than what you suggested yourself. :(
I found a question concerning this issue on the Telerik forums:
The behavior you have observed is expected as the categorical charts
(bar, area etc.) require a matching set of data points (the value can
be null but it should persist in the data). I am afraid there is no
built-in functionality which will automatically set 0 for the missing
values - you should modify your data.
I am afraid the implementation of this functionality is not in our immediate plans, however we may consider it for future versions of the product.
I haven't found more recent information, but as far as I know this hasn't been fixed.
It' looks like I'm out of luck and I need to fix up the data. In my actual solution I'm doing that server-side, but for posterity if anyone needs a kickstart with a purely js fix, this is the starting point:
function fixData(data) {
var lookup =[], start = [], name = [], result =[];
for (i = 0, len = data.length; i < len; ++i) {
start[data[i].Start] = true;
name[data[i].Name] = true;
lookup[data[i].Start + "," + data[i].Name] = data[i].Value;
}
for (var currentStart in start) {
for (var currentName in name) {
var entry = {Start: currentStart, Name: currentName};
entry.Value = lookup[currentStart + "," + currentName] || 0;
result.push(entry);
}
}
return result;
}
JSFiddle: http://jsfiddle.net/12ob7qmx/8/
Putting an Angular watch on a multidimensional array is proving problematic
I have a screen where the user will see two teams (outer array) with a teamsheet(inner array) for each team. He is able to drag and drop the players to change the batting order.
The battingOrder is updated according to the player's spot in the array.
The following solution is a bit of a cop out/short term, but it does solve my immediate stumbling block.
A more preferable solution would be appreciated though.
The following code is in my controller.
$scope.$watch(
"Teams[0].TeamSheet",
function (newValue, oldValue) {
for (var i = 0; i < newValue.length; i++) {
newValue[i].battingOrder = i + 1;
}
},
true
);
$scope.$watch(
"Teams[1].TeamSheet",
function (newValue, oldValue) {
for (var i = 0; i < newValue.length; i++) {
newValue[i].battingOrder = i + 1;
}
},
true
);
$scope.Teams = [{
TeamName: "South-Africa",
TeamSheet: [
{
name: "A Peterson",
battingOrder: 1,
mode: "view"
},
{
name: "Riley Rossouw",
battingOrder: 2,
mode: "view"
},
{
name: "H Amla",
battingOrder: 3,
mode: "view"
},
{
name: "F Du Plessis",
battingOrder: 4,
mode: "view"
},
{
name: "AB De Villiers",
battingOrder: 5,
mode: "view"
}
]
},
{
TeamName: "Australia",
TeamSheet: [
{
name: "D Warner",
battingOrder: 1,
mode: "view"
},
{
name: "S Watson",
battingOrder: 2,
mode: "view"
},
{
name: "M Clarke",
battingOrder: 3,
mode: "view"
},
{
name: "C Rogers",
battingOrder: 4,
mode: "view"
},
{
name: "S Smith",
battingOrder: 5,
mode: "view"
}
]
}];
you can try to update batting order directly inside the view:
<div ng-repeat="member in team" ng-init="member.battingOrder = $index">
</div>
then you do not need to use $watch
EDIT
the previous solution will not work after you swap items in your array. Use the following code to overcome this problem:
<body ng-controller="MainCtrl">
<div ng-repeat="member in team">
{{setIndex(member,$index)}}
{{member.name}},{{member.index}}
</div>
<button ng-click="swap()">swap first with last</button>
</body>
controller:
app.controller('MainCtrl', function($scope) {
$scope.team = [ { index: 0, name : 'first' }, { index: 0, name : 'second' }, { index: 0, name : 'third' } ];
$scope.swap = function () {
var tmp = $scope.team[0];
$scope.team[0] = $scope.team[2];
$scope.team[2] = tmp;
}
$scope.setIndex = function (member, index)
{
member.index = index;
}
});
http://plnkr.co/edit/V3ixkww7dxcx8uZ7f0hj?p=preview