JSON re-grouping with for each method in AngularJs - angularjs

I am new in angular and i want to re-group a JSON. Is it possible to do with angular.forEach() method?
[
{
"doc":{
"Title":"Main",
"name":"Ajith",
"Day":"03",
"count":3
}
},
{
"doc":{
"Title":"starters",
"name":"Saji",
"Day":"01",
"count":39
}
},
{
"doc":{
"Title":"desert",
"name":"Sajeeb",
"Day":"02",
"count":63
}
},
{
"doc":{
"Title":"Main",
"name":"Suith",
"Day":"03",
"count":3
}
},
{
"doc":{
"Title":"starters",
"name":"Manu",
"Day":"01",
"count":9
}
}
]
I want the output should be like following.
{
"order":[
{
"Day":"01",
"Title":"starters",
"items":[
{
"name":"Saji",
"count":39
},
{
"name":"Manu",
"count":9
}
]
},
{
"Day":"02",
"Title":"desert",
"items":[
{
"name":"Sajeeb",
"count":63
}
]
},
{
"Day":"03",
"Title":"Main",
"items":[
{
"name":"Ajith",
"count":3
},
{
"name":"Suith",
"count":3
}
]
}
]
}
To regroup with angular.forEach() method.
Please help. Thanks.

https://jsfiddle.net/9fwtm0a0/4/
var days = [];
arr.forEach(function(d) {
var day = parseInt(d.doc.Day);
var item = { name: d.doc.name, count: d.doc.count };
if (days[day])
days[day].items.push(item);
else
days[day] = { Day: '0' + day, Title: d.doc.Title, items: item]};
});
days.sort(function (x, y) {
return parseInt(x.Day) > parseInt(y.Day);
});
var eventsinOrder = { order: days };
You don't really need the Angular forEach but you can easily substitute it in:
var days = [];
angular.forEach(arr, function (val, key) {
var day = parseInt(val.doc.Day);
var item = { name: val.doc.name, count: val.doc.count };
if (days[day])
days[day].items.push(item);
else
days[day] = { Day: '0' + day, Title: val.doc.Title, items: [item]};
});
days.sort(function (x, y) {
return parseInt(x.Day) > parseInt(y.Day);
});
var eventsinOrder = { order: days };
Either way you go you will still need to make use of the sort function (or any equivalent) to perform the sorting while you're building this resultant object.

Related

Date range picker for extjs?

Is there a good date-range picker for ExtJs?
Something like this: http://www.daterangepicker.com/?
I whipped this up in about 2 hours, so I'm sure there are some lingering bugs and things left to be desired, but it at least gets you started with a custom date range component. Here's my Fiddle. And the code:
Ext.define('DatePickerEnhanced', {
extend: 'Ext.picker.Date',
alias: 'widget.datePickerEnhanced',
config: {
startDate: null,
endDate: null
},
isDateRange: true,
isDragging: false,
initComponent: function () {
this.callParent()
this.on({
mouseover: {
element: 'el',
fn: 'onMouseOverEnhanced',
delegate: 'td.x-datepicker-cell',
scope: this
}
});
},
handleDateClick: function (e, t) {
this.callParent(arguments)
if (this.isDateRange) {
if (this.isDragging) {
this.isDragging = false;
var startCell = this.getCellByValue(this.startCell)
if (startCell) {
Ext.get(startCell).addCls(this.selectedCls)
}
this.setEndDate(new Date(this.getCellDateValue(this.activeCell)))
this.updateDateRange(this.startCell, this.endCell);
} else {
this.setStartDate(new Date(this.getCellDateValue(this.activeCell)))
this.isDragging = true;
this.updateDateRange(this.getCellDateValue(), -1);
}
}
},
getCellByValue: function (value) {
var cells = this.cells.elements;
for (var i = 0; i < cells.length; i++) {
var cell = cells[i]
if (cell.firstChild.dateValue === value) {
return cell;
}
}
},
onMouseOverEnhanced: function (e, target, eOpts) {
if (this.isDragging) {
this.updateDateRange(this.getCellDateValue(), this.getCellDateValue(target));
}
},
updateDateRange: function (startValue, endValue) {
var cells = this.cells.elements;
var selectedCls = this.selectedCls;
for (var i = 0; i < cells.length; i++) {
var cell = Ext.fly(cells[i])
var dateValue = this.getCellDateValue(cells[i]);
if (dateValue !== startValue && (dateValue < startValue || dateValue > endValue)) {
cell.removeCls(selectedCls)
} else {
cell.addCls(selectedCls)
}
}
},
getCellDateValue: function (cell) {
return cell && cell.firstChild.dateValue || this.startCell;
},
getDateRange: function () {
return {
start: this.getStartDate(),
end: this.getEndDate()
}
},
/**
* Update the contents of the picker for a new month
* #private
* #param {Date} date The new date
*/
fullUpdate: function (date) {
var me = this;
me.callParent(arguments);
Ext.asap(function () {
if (me.isDateRange && me.endCell) {
me.updateDateRange(me.startCell, me.endCell)
}
})
},
updateStartDate: function (value) {
this.startCell = value.getTime()
this.publishState('startDate', value);
},
updateEndDate: function (value) {
this.endCell = value.getTime()
this.publishState('endDate', value);
}
});
Ext.create('Ext.container.Viewport', {
viewModel: {
data: {
theStart: Ext.Date.add(new Date(), Ext.Date.DAY, 2),
theEnd: Ext.Date.add(new Date(), Ext.Date.DAY, 5)
}
},
items: [{
xtype: 'datePickerEnhanced',
minDate: new Date(),
bind: {
startDate: '{theStart}',
endDate: '{theEnd}'
}
}, {
xtype: 'displayfield',
fieldLabel: 'Start',
bind: {
value: '{theStart:date("m/d/Y")}'
}
}, {
xtype: 'displayfield',
fieldLabel: 'End',
bind: {
value: '{theEnd:date("m/d/Y")}'
}
}]
});

Dynamic angular chart

I'm trying to create a dynamic chart from userTemplate object.
I'm using this directive angular-flot and I want create the dataset and options of directive dynamically.
Its work but I have this error
Error: [$rootScope:infdig] http://errors.angularjs.org/1.2.21/$rootScope/infdig?p0=10&p1=%5B%5B%22fn%3…ection%5C%22%3A%7B%5C%22color%5C%22%3A%5C%22%2354728c%5C%22%7D%7D%22%5D%5D
at Error (native)
at http://mwm3-gui/asset/script/vendor/angular2.1/angular.min.js:6:450
at k.$get.k.$digest (http://mwm3-gui/asset/script/vendor/angular2.1/angular.min.js:110:66)
at k.$get.k.$apply (http://mwm3-gui/asset/script/vendor/angular2.1/angular.min.js:112:173)
at http://mwm3-gui/asset/script/vendor/angular2.1/angular.min.js:122:253
at e (http://mwm3-gui/asset/script/vendor/angular2.1/angular.min.js:37:440)
at http://mwm3-gui/asset/script/vendor/angular2.1/angular.min.js:41:120
HTML
<div ng-repeat="panel in row.panels" class="{{panel.columnClass}}" resizable id="{{panel.id}}" r-directions="['right']">
<flot dataset="getDataForChart(panel)" options="getOptionForChart(panel)" height="{{panel.graph.height}}"></flot>
</div>
CONTROLLER
$scope.userTemplate = [
{
blockId: 'blockUno',
title: 'Block title',
rows: [
{
rowId: 'rowUno',
title: 'Row Title 1',
panels: [
{
id: 'palel-report-1',
title: 'uno',
columnClass: 'col-md-4',
graph: {
height: 250,
type: "BAR",
countBy: "status"
}
},
{
id: 'palel-report-2',
title: 'due',
columnClass: 'col-md-4',
graph: {
height: 250,
type: "PIE",
countBy: "status"
}
},
{
id: 'palel-report-3',
title: 'tre',
columnClass: 'col-md-4',
graph: {
height: 250,
type: "BAR",
countBy: "status"
}
}
]
}
],
tables: []
}
];
$scope.getDataForChart = function(panel) {
var graphData = [];
var countBy = panel.graph.countBy;
var arr = $scope.reportingData;
for (var i = 0; i < arr.length; i++) {
var valueOfkey = arr[i][countBy];
graphData.push(valueOfkey);
}
var a = [], b = [], prev;
graphData.sort();
for (var i = 0; i < graphData.length; i++) {
if (graphData[i] !== prev) {
a.push(graphData[i]);
b.push(1);
} else {
b[b.length - 1]++;
}
prev = graphData[i];
}
var graphData = [];
for (var i = 0; i < a.length; i++) {
var singleO = {label: '' + a[i], data: [[i, b[i]]]};
graphData.push(singleO);
}
return graphData;
};
$scope.getOptionForChart = function(panel) {
var options = angular.copy($scope.defaultPlotOptions);
var typeGraph = panel.graph.type;
switch (typeGraph) {
case "BAR":
options.series.bars.show = true;
break;
case "LINE":
options.series.lines.show = true;
break;
case "PIE":
options.series.pie.show = true;
break;
case "POINT":
options.series.points.show = true;
break;
case "TABLE":
break;
}
return options;
};
The error you get is from an infinite digest loop.
In a couple of places you are calling functions that return new items each time. Here's an example from the docs linked from the error message you received that suggests this may cause this error:
One common mistake is binding to a function which generates a new
array every time it is called. For example:
<div ng-repeat="user in getUsers()">{{ user.name }}</div>
$scope.getUsers = function() { return [ { name: 'Hank' }, { name: 'Francisco' } ]; };
Since getUsers() returns a new array, Angular
determines that the model is different on each $digest cycle,
resulting in the error. The solution is to return the same array
object if the elements have not changed:
var users = [ { name: 'Hank' }, { name: 'Francisco' } ];
$scope.getUsers = function() { return users; };
In your code, you are doing the same binding to getDataForChart and getOptionForChart.

JSON array, how to get index of the object with higher value of the given attribute?

I have following JSON array of the objects:
var dummyData = [
{
hr:"10",
dial_success_rate:"23",
appt_success_rate:"60",
appt_100_numbers:"10",
},
{
hr:"11",
dial_success_rate:"24",
appt_success_rate:"60",
appt_100_numbers:"10",
},
{
hr:"12",
dial_success_rate:"25",
appt_success_rate:"60",
appt_100_numbers:"10",
},
{
hr:"13",
dial_success_rate:"26",
appt_success_rate:"60",
appt_100_numbers:"10",
},
{
hr:"14",
dial_success_rate:"27",
appt_success_rate:"60",
appt_100_numbers:"10",
},
{
hr:"15",
dial_success_rate:"28",
appt_success_rate:"60",
appt_100_numbers:"10",
},
{
hr:"16",
dial_success_rate:"29",
appt_success_rate:"60",
appt_100_numbers:"10",
},
{
hr:"17",
dial_success_rate:"30",
appt_success_rate:"60",
appt_100_numbers:"10",
},
{
hr:"18",
dial_success_rate:"45",
appt_success_rate:"60",
appt_100_numbers:"10",
},
{
hr:"19",
dial_success_rate:"40",
appt_success_rate:"60",
appt_100_numbers:"10",
},
{
hr:"20",
dial_success_rate:"39",
appt_success_rate:"60",
appt_100_numbers:"10",
},
{
hr:"21",
dial_success_rate:"55",
appt_success_rate:"60",
appt_100_numbers:"10",
},
{
hr:"22",
dial_success_rate:"12",
appt_success_rate:"60",
appt_100_numbers:"10",
},
{
hr:"23",
dial_success_rate:"9",
appt_success_rate:"60",
appt_100_numbers:"10",
},
];
I would like to get index of the object with highest value on the given attribute.
It means something like this:
$scope.getHigherItem = function(data, stat, info) {
var selectedValues = data.map(function(x) {
return parseFloat(x[stat]);
});
var i = selectedValues.indexOf(Math.max.apply(Math, selectedValues));
var result = {};
info.forEach(function(x) {
result[x] = data[i][x];
});
return result;
};
console.log($scope.getHigherItem(dummyData, "dial_success_rate", ["dial_success_rate"]));
Example above is returning higher value, but is not returning index of the object in the array.
How can i solve it please?
Many thanks for any advice.
I think all you need to do is add an attribute to the result which contain the index like following :
...
var result = {};
/*
info.forEach(function(x) {
result[x] = data[i][x];
});*/
result[stat] = data[i][stat]; // <-- INSTEAD OF FOREACH LOOP
result.index = i; // <-- HERE
return result;
var maxValue = Math.max(selectedValues);
var maxIndexes = []; //Array of indexes of == maxValue
for (_i = 0, _len = selectedValues.length; _i < _len; _i++) {
a = selectedValues[i];
if (a === max) {
maxIndexes.push(_i);
}
}
...
...
return {
result: result
maxIndexes: maxIndexes
}
With that you have an array which contains the indexes of all the objects on your selectedValues array that are equal to max. If you want the first of this just do maxIndexes[0]
Do all at once in the map-function:
var getHigherItem = function (data, stat) {
var compare, result = {};
var selectedValues = data.map(function (x, i) {
if (i == 0) {
compare = parseFloat(x[stat]);
} else if(compare < parseFloat(x[stat])){
compare = parseFloat(x[stat]);
result[stat] = parseFloat(x[stat]);
result['index'] = i;
}
});
return result;
};
console.log(getHigherItem(dummyData, "dial_success_rate"));

Updating highcharts dynamically with json response

I am trying to draw highcharts with the json response, however I can able to draw for the first time, but unable to update the series with new data
function get_chart(data) {
//alert('hello..' + data);
return {
xAxis: {
type: 'datetime',
labels: {
formatter: function() {
var monthStr = Highcharts.dateFormat('%b', this.value);
var firstLetter = monthStr.substring(0, 1);
return firstLetter;
}
}
},
title: {
text: data.measurementName
},
chart: {
height: 300,
width: 500,
type: 'column',
zoomType: 'x'
},
credits: {
enabled: false
},
plotOptions: {
series: {
cursor: 'pointer',
point: {
events: {
click: function() {
console.log ('Category: '+ this.category +', value: '+ this.y);
}
}
}
}
},
series: [{
name: 'Hours',
data: (function() {
var chart = [{key:data.measurementName, values:[]}];
var i = 0;
if(typeof(data) == 'string')return chart;
for(n in data.values){
data.values[n].snapshot = new Date(data.values[n].snapshot);
data.values[n].value = parseInt(data.values[n].value);
}
chart[0].values = data.values.map(function(arrayObj){
return [arrayObj.value]
});
return chart[0].values;
})()
}]
};
}
and I am calling this function like
$scope.renderChart = function(measurement){
$scope.showChart = false;
restApp.getMeasurementForCompID(comp.id, measurement.id).then(function(data){
console.log(data);
$scope.example_chart = get_chart(data);
console.log($scope.example_chart);
$scope.showChart = true;
});
}
Here getMeasurementForCompID is another function which gets the data from database.
What is the problem here? any help..
I used https://github.com/pablojim/highcharts-ng
I just alter the data object and the highcharts reflects the change.

angularJs filter nested object Track by

I created a custom filter, but its giving me an error
I created a fiddle here:
Fiddle
I have this user data:
data: [{
profile: {
firstName: 'John',
lastName: 'OConner'
}
}, {
profile: {
firstName: 'Smith',
lastName: 'OConner'
}
}, {
profile: {
firstName: 'James',
lastName: 'Bond'
}
}]
And I need to filter by the nested obj - profile by this
data: [{
column: {
label: 'firstName',
}
}, {
column: {
label: 'lastName',
}
}]
I can filter but is giving me this error:
this is my filter:
myApp.filter('testFilter', ['$filter',
function($filter) {
return function(items, selectedFilter) {
var returnArray = items;
var filtered = [];
var process = {};
process.filtered = [];
process.loop = function(obj, key) {
var filtered = [];
this.obj = obj;
this.key = key;
// console.log('obj--> ', obj);
// console.log('key--> ', key);
filtered = filtered.concat($filter('filter')(items, process.superFilter));
if (filtered.length > 0) {
process.filtered = filtered;
}
};
process.superFilter = function(value) {
var returnMe;
var originalValue = value.profile[process.key];
if (typeof(value) === 'String') {
originalValue = originalValue.toLowerCase();
}
if (originalValue === process.obj) {
console.log('found');
returnMe = value;
return returnMe;
}
};
if (Object.getOwnPropertyNames(selectedFilter).length !== 0) {
angular.forEach(selectedFilter, function(obj) {
filtered = filtered.concat($filter('filter')(items, obj));
});
returnArray = filtered;
// console.log('selectedFilter ', selectedFilter);
}
return returnArray;
};
}
]);
Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. How can I solve this issue?
You need to use track by as the error suggests. If you don't have a unique key to use you can use $index.
ng-repeat='talent in talents.data | testFilter:filterInput track by $index'
Here is a working example with your code: http://jsfiddle.net/hwT4P/

Resources