Create a 2 level json Array using Angular Js - javascript

I need to contruct a Json with 2 parts first of all I need to obtain a name of companies from an ApiRest it returns a Json with the name of the companies and a parameter that contains an address for each company that have de members of the company. The Json that I need to construct is something like this:`
[
{name: Company1,
members:
{ member1:
{
name: albert,
age: 16
},
member2:
{
name:joan,
age:18
}
}
},
{name: Company2,
members:
{ member1:
{
name: albert,
age: 16
},
member2:
{
name:joan,
age:18
}
}
}
]
The firts api rest is http://api1.getcompanyies and return :
[{
"_links": {
"url": {
"href": "http://api.company.members/1"
}
},
"name": "Company1",
},
{
"_links": {
"url": {
"href": "http://api.company.members/2"
}
},
"name": "Company2",
}, {
"_links": {
"url": {
"href": "http://api.company.members/3"
}
},
"name": "Company3"}
The second api Rest Response is:
{"employes": [
{
"name": "Mickael Ciani",
"age": "16"
},
{
"name": "Albert dd",
"age": "18"
}
]}
first I tried to do with nested $http but don't works:
$http(firstApi)
.then(function(res) {
$scope.ob = {};
angular.forEach(res.data.teams, function(value, key) {
var companyName = value.name;
$scope.ob[companyName] = {};
$scope.ob[companyName].memberUrl = alue._links.url.href;
$scope.teams2.push(value.name);
$http(paramsPlayers)
.then(function(res2) {
// construct the array
},
function() {}
);
});
return $scope;
},
function() {}
);
Then i tried to do without nested http but still don't work because the contruction of first object is incorrect , i think
$http(firstApi)
.then(function(res) {
$scope.ob = {};
angular.forEach(res.data.teams, function(value, key) {
var companyName = value.name;
$scope.ob[companyName] = {};
$scope.ob[companyName].memberUrl = alue._links.url.href;
$scope.teams2.push(value.name);
});
return $scope;
},
function() {}
);
$http(2apiparams)
.then(function(res2) {
//construct final json
},
function() {}
);
Thank You For all

You have to use $q.all for this scenario. I have written a angular service named CompanyService and a test implementation for the same. Hope this helps. You can use this service in your application. Take a look at promise chaining to get more idea on the implementation
var testData = {
companies: [{
"_links": {
"url": {
"href": "http://api.company.members/1"
}
},
"name": "Company1"
}, {
"_links": {
"url": {
"href": "http://api.company.members/2"
}
},
"name": "Company2"
}, {
"_links": {
"url": {
"href": "http://api.company.members/3"
}
},
"name": "Company3"
}],
memebers: {
"employes": [{
"name": "Mickael Ciani",
"age": "16"
},
{
"name": "Albert dd",
"age": "18"
}
]
}
};
angular.module('app', [])
.factory('CompanyService', function($http, $q) {
var COMPANY_API = 'your company api url';
var service = {};
service.getCompanies = function() {
//comment this for real implementation
return $q.when(testData.companies);
//uncomment this for real api
//return $http.get(COMPANY_API);
};
service.getMemebers = function(url) {
//comment this for real implementation
return $q.when(testData.memebers);
//uncomment this for real api
//return $http.get(url);
};
service.getAll = function() {
return service.getCompanies()
.then(function(companies) {
var promises = companies.map(function(company) {
return service.getMemebers(company._links.url.href);
});
return $q.all(promises)
.then(function(members) {
return companies.map(function(c, i) {
return {
name: c.name,
members: members[i].employes
};
});
});
});
};
return service;
})
.controller('SampleCtrl', function($scope, CompanyService) {
$scope.companies = [];
CompanyService.getAll()
.then(function(companies) {
$scope.companies = companies;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="SampleCtrl">
<pre>{{ companies | json }}</pre>
</div>

Related

Group and count values in an array

I have an array with objects, like the following.
b = {
"issues": [{
"fields": {
"status": {
"id": "200",
"name": "Backlog"
}
}
}, {
"fields": {
"status": {
"id": "202",
"name": "close"
}
}
}, {
"fields": {
"status": {
"id": "201",
"name": "close"
}
}
}]
};
I want to count how many issues have status close, and how many have backlog. I'd like to save the count in a new array as follows.
a = [
{Name: 'Backlog', count: 1},
{Name: 'close', count: 2}
];
I have tried the following.
b.issues.forEach(function(i) {
var statusName = i.fields.status.name;
if (statusName in a.Name) {
a.count = +1;
} else {
a.push({
Name: statusName,
count: 1
});
}
});
That however doesn't seem to be working. How should I implement this?
This is a perfect opportunity to use Array#reduce. That function will take a function that is applied to all elements of the array in order and can be used to accumulate a value. We can use it to accumulate an object with the various counts in it.
To make things easy, we track the counts in an object as simply {name: count, otherName: otherCount}. For every element, we check if we already have an entry for name. If not, create one with count 0. Otherwise, increment the count. After the reduce, we can map the array of keys, stored as keys of the object, to be in the format described in the question. See below.
var b = {
"issues": [{
"fields": {
"status": {
"id": "200",
"name": "Backlog"
}
}
}, {
"fields": {
"status": {
"id": "202",
"name": "close"
}
}
}, {
"fields": {
"status": {
"id": "201",
"name": "close"
}
}
}]
};
var counts = b.issues.reduce((p, c) => {
var name = c.fields.status.name;
if (!p.hasOwnProperty(name)) {
p[name] = 0;
}
p[name]++;
return p;
}, {});
console.log(counts);
var countsExtended = Object.keys(counts).map(k => {
return {name: k, count: counts[k]}; });
console.log(countsExtended);
.as-console-wrapper {
max-height: 100% !important;
}
Notes.
Array#reduce does not modify the original array.
You can easily modify the function passed to reduce to for example not distinguish between Backlog and backlog by changing
var name = c.fields.status.name;
into
var name = c.fields.status.name.toLowerCase();
for example. More advanced functionality can also easily be implemented.
Using ES6 Arrow functions you can do it with minimum syntax
var b = {
"issues": [{
"fields": {
"status": {
"id": "200",
"name": "Backlog"
}
}
}, {
"fields": {
"status": {
"id": "202",
"name": "close"
}
}
}, {
"fields": {
"status": {
"id": "201",
"name": "close"
}
}
}]
};
var countOfBackLog = b.issues.filter(x => {
return x.fields.status.name === "Backlog"
}).length
var countOfClose = b.issues.filter(x => {
return x.fields.status.name === "close"
}).length
a =[{Name: 'Backlog', count : countOfBackLog}, {Name: 'close', count : countOfClose}]
More about arrow functions here
You can write like this. It is dynamic.
var a = {};
for(var key in b["issues"]){
if(!a.hasOwnProperty(b["issues"][key].fields.status.name)){
a[b["issues"][key].fields.status.name] = 1;
}else{
a[b["issues"][key].fields.status.name] = a[b["issues"][key].fields.status.name]+1;
}
}
var c = [];
for(var key1 in a){
c.push({
name : key1,
count : a[key1]
});
}
Something like this should do the trick. Simply iterate over your data, keep 2 counters with the number of each type of issue, and create the data format you want in the end. Try it live on jsfiddle.
var b = {
"issues": [{
"fields": {
"status": {
"id": "200",
"name": "Backlog"
}
}
}, {
"fields": {
"status": {
"id": "202",
"name": "close"
}
}
}, {
"fields": {
"status": {
"id": "201",
"name": "close"
}
}
}]
};
var data = [];
for(var issue of b.issues){
var entryFound = false;
var tempObj = {
name: issue.fields.status.name,
count: 1
};
for(var item of data){
if(item.name === tempObj.name){
item.count++;
entryFound = true;
break;
}
}
if(!entryFound){
data.push(tempObj);
}
}
console.log(data);

use filter function using http request in angular

I am using typeahead of UI-bootstrap for search filter, now I am using data from controller but I want data from JSON using $http. But I am not able to take data from $http request in filter function.
current code
// Search Control
vm.searchCtrl = "";
var searchitems = [{
"name": "Adventure",
"category": "Activities"
}, {
"name": "Cycling",
"category": "Activities"
}, {
"name": "Local guided tours",
"category": "Activities"
}, {
"name": "Delux room",
"category": "Accommodations"
}, {
"name": "Super Delux room",
"category": "Accommodations"
}, {
"name": "Goa",
"category": "Destinations"
}, {
"name": "Bengaluru",
"category": "Destinations"
}];
vm.getSearchitems = function (search) {
var filtered = filterFilter(searchitems, search);
var results = _(filtered).groupBy('category').map(function (g) {
g[0].firstInCategory = true;
return g;
}).flatten().value();
return results;
}
But Now I want like this
$http.get('../assets/data/search.json').then(function (response) {
return vm.searchitems = response;
});
vm.getSearchitems = function (search) {
var filtered = filterFilter(searchitems, search);
var results = _(filtered).groupBy('category').map(function (g) {
g[0].firstInCategory = true;
return g;
}).flatten().value();
return results;
}
But "searchitems" are not getting.
You want to invoke your function only after you have the data from $http. So move your call to getSearchItems so it gets called from the $http.
$http.get('../assets/data/search.json').then(function (response) {
return vm.getSearchitems(response);
});
vm.getSearchitems = function (search) {
var filtered = filterFilter(searchitems, search);
var results = _(filtered).groupBy('category').map(function (g) {
g[0].firstInCategory = true;
return g;
}).flatten().value();
return results;
}

How to return object based on value in nested array? (Javascript)

I am trying to return all objects that have a specific 'id' in the nested array. In the sample data, I'd like to return all person objects with hobbies id of 2 (hiking).
The other question addresses the problem of finding all values in an array based on an object value.
This question differs from the previous because I need to return all objects based on a value inside of a nested array.
[
{
"id":111222,
"name":"Faye",
"age":27,
"hobbies":[
{
"id":2,
"name":"hiking"
},
{
"id":3,
"name":"eating"
}
]
},
{
"id":223456789001,
"name":"Bobby",
"age":35,
"hobbies":[
{
"id":2,
"name":"hiking"
},
{
"id":4,
"name":"online gaming"
}
]
}
]
function hasHobby(person, hobbyId) {
return person.hobbies.some(function(hobby) {
return hobby.id === hobbyId;
});
}
function filterByHobby(people, hobbyId) {
return people.filter(function(person) {
return hasHobby(person, hobbyId);
});
}
If you wanna use the new cool ES6 syntax:
function filterByHobby(people, hobbyId) {
return people.filter(
person => person.hobbies.some(
hobby => hobby.id === hobbyId
)
);
}
var arr = [
{
"id":111222,
"name":"Faye",
"age":27,
"hobbies":[
{
"id":2,
"name":"hiking"
},
{
"id":3,
"name":"eating"
}
]
},
{
"id":223456789001,
"name":"Bobby",
"age":35,
"hobbies":[
{
"id":2,
"name":"hiking"
},
{
"id":4,
"name":"online gaming"
}
]
}
];
arr.filter(function(obj) {
var hobbies = obj.hobbies;
var x = hobbies.filter(function(hob) {
if (hob.id == "2") return true;
});
if (x.length > 0) return true;
});
Try this, I think its solve your proble:
var arr = [{
"id": 111222,
"name": "Faye",
"age": 27,
"hobbies": [{
"id": 2,
"name": "hiking"
}, {
"id": 3,
"name": "eating"
}]
}, {
"id": 223456789001,
"name": "Bobby",
"age": 35,
"hobbies": [{
"id": 2,
"name": "hiking"
}, {
"id": 4,
"name": "online gaming"
}]
}];
var x = arr.filter(function(el) {
var rnel = el.hobbies.filter(function(nel) {
return nel.id == 2;
});
return rnel.length > 0 ? true :false;
});
alert(x.length);

Firebase - how to perform a where item in list query?

Given
The url root is: https://myApp.firebaseio.com
And
The data is:
{
"users": {
"u00001": {
"name": "Andy",
"teams": {
"t001": true,
"t003": true
}
},
...
},
"teams": {
"t001": {
"name": "Alpha Team"
},
"t002": {
"name": "Beta Team"
},
"t003": {
"name": "Gamma Team"
},
...
}
}
And
The teams Andy joins are ['t001', 't003']
Question:
Is it possible to use ONE query to get all the names of the teams that Andy joins? (find all the team names, where IDs are in ['t001', 't003'], e.g. expect ["Alpha Team", "Gamma Team"] )
Thanks in advance.
This should work:
var ref = new Firebase('https://myApp.firebaseio.com');
ref.child('users/u00001/teams').on('value', function(teamKeys) {
var teamNames = [];
teamKeys.forEach(function(teamKey) {
ref.child('teams').child(teamKey.key()).once('value', function(teamSnapshot) {
teamNames.push(teamSnapshot.val().name);
if (teamNames.length == teamKeys.numChildren()) {
console.log('All team names loaded');
}
});
});
})
If you're worried about the loading time and number of round-trips, see Speed up fetching posts for my social network app by using query instead of observing a single event repeatedly
var data = { "users": { "u00001": { "name": "Andy", "teams": { "t001": true, "t003": true } }, }, "teams": { "t001": { "name": "Alpha Team" }, "t002": { "name": "Beta Team" }, "t003": { "name": "Gamma Team" } } }
function getNames(data, user) {
var res = [];
var teams = [];
Object.keys(data.users).forEach(k => {
if (data.users[k].name == user) {
Object.keys(data.users[k].teams).forEach(t => teams.push(t))
}
});
Object.keys(data.teams).forEach(t => {
if (teams.indexOf(t) > -1) {
res.push(data.teams[t].name);
}
});
return res;
}
document.write(JSON.stringify(getNames(data, "Andy")));

How to return and array inside a JSON object in Angular.js

Imagine the following JSON API:
[
{
"id": "1",
"name": "Super Cateogry",
"products": [
{
"id": "20",
"name": "Teste Product 1"
},
{
"id": "21",
"name": "Teste Product 2"
},
{
"id": "22",
"name": "Teste Product 3"
}
]
}
]
Is there anyway for me to only return the products array with Angularjs?
I have a simple service calling the JSON:
services.factory("ProductService", function($http) {
return {
"getProducts": function() {
return $http.get("/product/index");
}
};
});
That is being called in the controller like so:
components.success(function(data) {
$scope.products = data;
});
But it returns the whole JSON as expected, I need it to return only the "products" array so I can iterate through it.
PS: This is merely a simple example to illustrate the problem, I realize that I could change the API to fit my needs in this case, but that's not the point.
You would just assign the products array to your scope property...
components.success(function(data) {
$scope.products = data[0].products;
});
You could customize it via a promise, and do it yourself.
"getProducts": function() {
var promise = $q.defer();
$http.get("/product/index").success(function(data){
promise.resolve(data && data.products);
}).error(function(msg){
promise.reject(msg);
})
return promise.promise;
}
How to use:
getProducts().then(
function(data) {
$scope.products = data;
},
function(msg){
alert('error')
}
);

Categories

Resources