AngularJS JSON scope - javascript

I'm trying to make my Angular controller more generic in the way it handles JSON array of objects.
Currently I have the following defined:
$scope.Data = [];
and I pull across the data in my template like:
ng-repeat="item in Data.category[3].values
My JSON looks like:
"category": [{
"name": "cat1",
"behaviour": "normal",
"selected": 0,
"values": [{
"label": "define",
"count": 6
}]
}, {
"name": "cat2",
"behaviour": "normal",
"selected": 0,
"values": [{
"label": "type",
"count": 6
}]
}, {
"name": "Company",
"behaviour": "multi-select",
"selected": 0,
"values": [{
"label": "VW",
"count": 4
}, {
"label": "Renault",
"count": 1
}, {
"label": "Fiat",
"count": 1
}]
}, {
"name": "Make",
"behaviour": "multi-select",
"selected": 0,
"values": [{
"label": "Gold",
"count": 3
}]
}, {
"name": "Color",
"behaviour": "normal",
"selected": 0,
"values": [{
"label": "White",
"count": 3
}, {
"label": "Blue",
"count": 2
}, {
"label": "Green",
"count": 1
}]
}]
What I'm trying to do is rather than access a specific index with:
Data.category[3].values
I'd like to loop through category and grab a list of index items so I can use like:
Data.category[Color].values
where Color is found in the list, and I can bring back the values for that specific element, is that possible?

You would use filter instead, you can also pass Color value dynamically through scope.
Markup
ng-repeat="item in (Data.category| {name: 'Color'}: true)[0].values
Update
You could pass Color variable dynamically through another scope variable, like $scope.color = 'Color' so the ng-repeat will become
Html
ng-repeat="item in (Data.category| {name: color}: true)[0].values

I am not sure this is what you want but if you need to display value in function of color attribute you could do this in your controller:
$scope.dataToDisplay = [];
for(var i = 0; i < $scope.Data.length ; i++){
{
if($scope.Data.color == 'yourcolor') {
$scope.dataToDisplay.push($scope.Data[i].values)
}
}
And in your HTML you just display dataToDisplay

Related

How can i merge an array of objects in Nodejs with underscore

In my case i have a 2 db queries which are objects, one which returns all possible items which consists of a key and name field and then the other is a object which has the key, name and value field. What i am trying to do is to merge both objects where object 1 is the main object and object 2 should be merged into it.
What i ideally want is to return all items in Data2 with the value field merged into data2 and 0 if there is no data in data 1. if thats not possible i would be ok with no value in items in data 2 but i get even a strange result for that.
Fyi i am using underscore
const data1 = [
{
"count": 2,
"key": "c28f7ead-d87b-4ad5-b6b3-1f204b013b50",
"name": "Notes Written"
},
{
"count": 1,
"key": "d0181c74-22a9-4f99-9cc9-df3467c51805",
"name": "Pop-Bys Delivered"
},
{
"count": 2,
"key": "90d142ea-6748-4781-b2b9-4f05aab12956",
"name": "Database Additions"
},
{
"count": 1,
"key": "723e95dd-8c47-48ed-b9c3-1b010b092a1b",
"name": "Referals Given"
}
]
const data2 = [
{
"key": "8646ec5d-7a72-49bd-9a68-cf326d1c4a14",
"name": "Calls Made"
},
{
"key": "c28f7ead-d87b-4ad5-b6b3-1f204b013b50",
"name": "Notes Written"
},
{
"key": "d0181c74-22a9-4f99-9cc9-df3467c51805",
"name": "Pop-Bys Delivered"
},
{
"key": "90d142ea-6748-4781-b2b9-4f05aab12956",
"name": "Database Additions"
},
{
"key": "723e95dd-8c47-48ed-b9c3-1b010b092a1b",
"name": "Referals Given"
},
{
"key": "0f054686-ef13-4993-ac5b-f640ceeaaa8d",
"name": "Referals Received"
}
]
console.log(_.extend( data2, data1 ))
Here is a Replit example Sample Code
Using reduce, iterate over data1 while updating a Map of key-count pairs
Using each, iterate over data2 and set the value to the value of the key from the map, or 0 if it doesn't exist
const
data1 = [ { "count": 2, "key": "c28f7ead-d87b-4ad5-b6b3-1f204b013b50", "name": "Notes Written" }, { "count": 1, "key": "d0181c74-22a9-4f99-9cc9-df3467c51805", "name": "Pop-Bys Delivered" }, { "count": 2, "key": "90d142ea-6748-4781-b2b9-4f05aab12956", "name": "Database Additions" }, { "count": 1, "key": "723e95dd-8c47-48ed-b9c3-1b010b092a1b", "name": "Referals Given" } ],
data2 = [ { "key": "8646ec5d-7a72-49bd-9a68-cf326d1c4a14", "name": "Calls Made" }, { "key": "c28f7ead-d87b-4ad5-b6b3-1f204b013b50", "name": "Notes Written" }, { "key": "d0181c74-22a9-4f99-9cc9-df3467c51805", "name": "Pop-Bys Delivered" }, { "key": "90d142ea-6748-4781-b2b9-4f05aab12956", "name": "Database Additions" }, { "key": "723e95dd-8c47-48ed-b9c3-1b010b092a1b", "name": "Referals Given" }, { "key": "0f054686-ef13-4993-ac5b-f640ceeaaa8d", "name": "Referals Received" } ];
const map = _.reduce(
data1,
(map, { key, count }) => map.set(key, count),
new Map
);
_.each(
data2,
e => e.value = map.get(e.key) || 0
);
console.log(data2);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.13.1/underscore-min.js" integrity="sha512-ZuOjyqq409+q6uc49UiBF3fTeyRyP8Qs0Jf/7FxH5LfhqBMzrR5cwbpDA4BgzSo884w6q/+oNdIeHenOqhISGw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

Push keys and values dynamically in Typescript

I want to push into array of objects keys and values dynamically. I thought that was pretty simple, something like:
list.forEach(element => {
element["carAttributes"].map((o) =>
{
this.car.push(
{
o.Name: o.Value
}
);
})
});
but it's not working because { o: any; } is not assignable to type CarInterface where CarInterface is:
export interface CarInterface {
"name": string;
}
o returns me something like
{"Name": "name", "Value": "Mercedes"}
what I have to do is take the value of the key Name and the value of the key Value and put everything in one object like:
{"name": "Mercedes"}
I have many values so i have to push everything in this.car list. Is that possible?
EDIT:
It could be something like that
{
"Cars": [{
"carAttributes": [{
"Name": "name",
"Value": "Mercedes"
}, {
"Name": "color",
"Value": "grey"
}, {
"Name": "model",
"Value": "A220"
}],
"available": true,
},{
"carAttributes": [{
"Name": "name",
"Value": "Mercedes"
}, {
"Name": "color",
"Value": "red"
}, {
"Name": "model",
"Value": "B250E"
}],
"available": false,
}]
}
I need to create an array of objects for each car that has this kind of structure
[
{"name": "Mercedes", "color": "grey", "model": "A220"},
{"name": "Mercedes", "color": "red", "model": "B250E"},
]
That's it.

Add columns value in react.js

What is the best approach to add all the columns value?
json
[
{
"id": "men",
"label": "men",
"value": 3,
"color": "#468df3"
},
{
"id": "women",
"label": "women",
"value": 5,
"color": "#ba72ff"
},
{
"id": "children",
"label": "children",
"value": 5,
"color": "#a1cfff"
}
]
I am fetching data from the server I like to add all the values and display it in the console.
For example const value = 3+5+5 = 13 in console.
That's not related to reactjs, simply
let raw = '[{"id": "men","label": "men","value": 3,"color": "#468df3"},{"id": "women","label": "women","value": 5,"color": "#ba72ff"},{"id": "children","label": "children","value": 5,"color": "#a1cfff"}]';
let data = JSON.parse(raw);
let sum_value = data.reduce((sum, current)=>{
return sum + current.value
}, 0);
console.log(sum_value);

Analysis Paralysis in looping over JSON data to populate select box with optgroup sections

I have Analysis Paralysis and need some input. I can modify the SQL query, the JavaScript, AND/or the CFML controller (all code has been posted below).
All I'm looking to do is to populate a select box with options and optgroups. The optgroup is what is tripping me up here.
The sql is pretty basic and looks like this:
SELECT
g.groupID,
g.groupLabel,
u.unitLabel,
u.unitID
FROM
group g
LEFT JOIN unit u ON g.groupID = u.groupID
And the CFML loop(s) is as follows (this is also where I believe the adjustment should be made with some logic such as if thisGroupLabel matches the preGroupLabel, stay within loop and keep adding unitLabel and unitIDs) but is there a more efficient way?:
local.data.unitLabels = [];
for(local.row in local.__unitLabels){
local.unit = {};
local.unit.groupLabel = local.row.groupLabel;
local.unit.unitLabel = local.row.unitLabel;
local.unit.unitID = local.row.unitID;
// loop over the array so that we can identify which one needs to be preselected
for(local.dataValue in local.data.unitDetails){
if (local.unit.unitID eq local.dataValue.unitID) {
local.unit.selected = 'selected';
} else {
local.unit.selected = '';
}
}
arrayAppend(local.data.unitLabels, local.unit);
}
The JSON data looks like this but I have access to the query so I can reformat it if needed:
{
"data": {
"selectDataOptions": [{
"groupLabel": "COMPLETION",
"selected": "",
"unitID": 1,
"unitLabel": "Completion"
}, {
"groupLabel": "DISTANCE",
"selected": "",
"unitID": 2,
"unitLabel": "Meters"
}, {
"groupLabel": "DISTANCE",
"selected": "",
"unitID": 3,
"unitLabel": "Miles"
}, {
"groupLabel": "DISTANCE",
"selected": "",
"unitID": 4,
"unitLabel": "Yards"
}, {
"groupLabel": "TIME",
"selected": "",
"unitID": 5,
"unitLabel": "Hours"
}, {
"groupLabel": "TIME",
"selected": "",
"unitID": 5,
"unitLabel": "minutes"
}, {
"groupLabel": "TIME",
"selected": "",
"unitID": 5,
"unitLabel": "Seconds"
}]
}
}
As it stands, my select box looks like this (roughly):
<select>
<optgroup>COMPLETION</optgroup>
<option>Complettion</option>
<optgroup>DISTANCE</OPTGROUP>
<option>Meters</option>
<optgroup>DISTANCE</optgroup>
<option>Miles</option>
<optgtroup>DISTANCE</optgroup>
<option>Yards</option>
<optgtroup>TIME</optgroup>
<option>Hours</option>
<optgtroup>TIME</optgroup>
<option>Minutes</option>
</select>
Notice that the optgroup Distance and TIME are repeated. The desired output would look like this:
<select>
<optgroup>COMPLETION</optgroup>
<option>Complettion</option>
<optgroup>DISTANCE</OPTGROUP>
<option>Meters</option>
<option>Miles</option>
<option>Yards</option>
<optgroup>TIME</optgroup>
<option>Hours</option>
<option>Mintues</option>
</select>
Is the issue how to construct a JSON string that Select2 can understand? I'd suggest creating a nested array of children for each GroupLabel, as described in the documentation under Grouped Data.
CF11+ and Lucee 4.5+ support cfloop "group", which would make things a lot easier. Just cfloop through the query and group by "groupLabel". (NB: Don't forget to modify the SQL query and ORDER BY g.groupLabel so the grouping works as expected.)
TryCF.com Example
Code:
data= [];
cfloop(query="qDemo", group="groupLabel") {
children = [];
cfloop() {
arrayAppend(children, {"id": qDemo.unitID, "text": qDemo.unitLabel});
}
arrayAppend(data, {"text" : qDemo.GroupLabel, "children" : children });
}
writeDump(serializeJSON(data));
Result:
[
{
"text": "COMPLETION",
"children": [
{
"text": "Completion",
"id": 1
}
]
},
{
"text": "DISTANCE",
"children": [
{
"text": "Meters",
"id": 2
},
{
"text": "Miles",
"id": 3
},
{
"text": "Yards",
"id": 4
}
]
},
{
"text": "TIME",
"children": [
{
"text": "Hours",
"id": 5
},
{
"text": "minutes",
"id": 5
},
{
"text": "Seconds",
"id": 5
}
]
}
]

How to merge array of objects with a property at any level in javascript?

Here is my array objects
var skus = [
{
"id": "1",
"active": true,
"attributes": {
"color": "pink",
"size": "small",
"material": "plastic"
},
"price": 899
},{
"id": "2",
"object": "sku",
"active": true,
"attributes": {
"color": "blue",
"size": "medium",
"material": "plastic"
},
"price": 500
},{
"id": "3",
"object": "sku",
"active": true,
"attributes": {
"color": "blue",
"size": "medium",
"material": "metal"
},
"price": 600
}
]
I want the output something like this :
finalOutput = {
"plastic" : [{id:1,...},{id:2,...}],
"metal" : [{id:3,...}]
}
So basically, I want to merge all the objects which have same attributes.material value.
Use lodash's _.groupBy() to collect the objects by their attributes.material.
var skus = [{"id":"1","active":true,"attributes":{"color":"pink","size":"small","material":"plastic"},"price":899},{"id":"2","object":"sku","active":true,"attributes":{"color":"blue","size":"medium","material":"plastic"},"price":500},{"id":"3","object":"sku","active":true,"attributes":{"color":"blue","size":"medium","material":"metal"},"price":600}];
var result = _.groupBy(skus, 'attributes.material');
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
... ok, let's have a look at Usman's approach ...
var skus = [{ "id": "1", "active": true, "attributes": { "color": "pink", "size": "small", "material": "plastic" }, "price": 899 }, { "id": "2", "object": "sku", "active": true, "attributes": { "color": "blue", "size": "medium", "material": "plastic" }, "price": 500 }, { "id": "3", "object": "sku", "active": true, "attributes": { "color": "blue", "size": "medium", "material": "metal" }, "price": 600 }];
var obj = {};
skus.forEach(o => {
if(!obj.hasOwnProperty(o.attributes.material)) {
obj[o.attributes.material] = [o];
} else {
obj[o.attributes.material].push(o);
}
});
console.log(obj);
.as-console-wrapper { max-height: 100%!important; top: 0; }
... it is based on an external object obj that serves both purposes, being the final result but also being the collecting reference for the time of iterating the given data structure skus.
Then there is a lookup for an existing property/key on obj that does match the value of a certain substructure of skus. In case obj does not yet features this key, an array gets assigned to a newly created property. This array already holds a single item, the current object of the skus iteration.
If the property already exists - by then it references an array - the current object of the skus iteration just will be pushed into this array.
Having finished the forEach iteration of skus, obj will hold one or more lists of former skus-items, each mapped to a single key/property of unique attributes.material-values derieved from skus-items.
A good solution provides a function that encloses all of this code.
An even better solution will come up with a more generic and better reusable approach. Since the whole matter is about transforming list based data structures, map and reduce are good candidates for it. Here the latter is the right one for map only is capable of mapping one list item into just another one, thus it does not change the list itself but it transforms each of a list's items. reduce is far more flexible for it provides into it's callback a collector/accumulator object in addition to the currently iterated item. This collector can be provided as initial value and it's type/structure is free of choice.
A reduce based approach that meets the OP's requirements needs to be customizable in terms of how to access a certain property that's value then is base of a (gouped) list of objects that share this special property value.
A working example then might look like the next provided one ...
var skus = [{ "id": "1", "active": true, "attributes": { "color": "pink", "size": "small", "material": "plastic" }, "price": 899 }, { "id": "2", "object": "sku", "active": true, "attributes": { "color": "blue", "size": "medium", "material": "plastic" }, "price": 500 }, { "id": "3", "object": "sku", "active": true, "attributes": { "color": "blue", "size": "medium", "material": "metal" }, "price": 600 }];
function collectItemGroupedByGenericKey(collector, item) {
var
groupKey = collector.getGroupKey(item),
store = collector.store,
storedList = store[groupKey];
if (!storedList) {
storedList = store[groupKey] = [];
}
storedList.push(item);
return collector;
}
var materialList = skus.reduce(collectItemGroupedByGenericKey, {
getGroupKey: function (item) { return item.attributes.material; },
store: {}
}).store;
console.log('materialList : ', materialList);
.as-console-wrapper { max-height: 100%!important; top: 0; }

Categories

Resources