I am trying to access the "list" parameter in the following data set received from [Open weather map][1]. I basically need to access the list layer in the below set where I can get the temp parameter.
{
"cod":"200",
"message":0.0046,
"cnt":37,
"list":[
{
"dt":1518080400,
"main":{
"temp":297.81,
"temp_min":295.457,
"temp_max":297.81,
"pressure":1011.64,
"sea_level":1018.79,
"grnd_level":1011.64,
"humidity":71,
"temp_kf":2.35
},
"weather":[
{
"id":800,
"main":"Clear",
"description":"clear sky",
"icon":"01d"
}
],
"clouds":{
"all":0
},
"wind":{
"speed":3.76,
"deg":322.502
},
"sys":{
"pod":"d"
},
"dt_txt":"2018-02-08 09:00:00"
},
{
"dt":1518091200,
"main":{
"temp":298.03,
"temp_min":296.468,
"temp_max":298.03,
"pressure":1010.47,
"sea_level":1017.64,
"grnd_level":1010.47,
"humidity":65,
"temp_kf":1.57
},
"weather":[
{
"id":802,
"main":"Clouds",
"description":"scattered clouds",
"icon":"03d"
}
],
"clouds":{
"all":48
},
"wind":{
"speed":4.77,
"deg":315
},
"sys":{
"pod":"d"
},
"dt_txt":"2018-02-08 12:00:00"
},
{
"dt":1518102000,
"main":{
"temp":294.89,
"temp_min":294.104,
"temp_max":294.89,
"pressure":1011.17,
"sea_level":1018.11,
"grnd_level":1011.17,
"humidity":77,
"temp_kf":0.78
},
"weather":[
{
"id":802,
"main":"Clouds",
"description":"scattered clouds",
"icon":"03d"
}
],
"clouds":{
"all":44
},
"wind":{
"speed":4.91,
"deg":287.002
},
"sys":{
"pod":"d"
},
"dt_txt":"2018-02-08 15:00:00"
}
]}
I am not sure as to how to go about it. I keep on getting this error "ERROR Error: Cannot find a differ supporting object"
I tried looping through it like below
this.http.get('http://api.openweathermap.org/data/2.5/forecast?id=3362024&APPID=bbcf57969e78d1300a815765b7d587f0').subscribe(data => {
this.items = JSON.stringify(data);
console.log(this.items);
for(var i = 0; i < this.items.length; i++){
this.min = this.items[i].dt;
console.log(this.min);
}
});
Try this. Make sure you import following import on top of the component
import 'rxjs/Rx';
or
import 'rxjs/add/operator/map'
getData(){
this.http.get('https://api.openweathermap.org/data/2.5/forecast?id=3362024&APPID=bbcf57969e78d1300a815765b7d587f0')
.map(res=>res.json()).subscribe(data => {
this.items = data;
console.log(this.items);
for(var i = 0; i < this.items.list.length; i++){
this.min = this.items.list[i].main;
console.log(this.min);
}
});
}
WORKING DEMO
Do console.log(data); and check what kind of data you are getting from API.
If you are getting JSON data from API, then do not do JSON.stringify(data);
If you are getting JSON contained in string then do JSON.parse();
After this you will get JSON in a variable and you can iterate it as follows
Also, do not post your api key in question , others can hit API using your api key
this.http.get('http://api.openweathermap.org/data/2.5/forecast?id=yourId&APPID=yourapikey')
.subscribe(data => {
var res = JSON.parse(data); //if you are getting JSON in a string, else do res = data;
for(var i = 0; i < res.list.length; i++){
console.log(res.list[i].main.temp);
}
});
Considering you are correctly getting json response:=>
One way is :
if you know response in advance and its basic structure is always same then:
you can create a model object similar to the json response and assign the json response to that object and access any values.
e.g.
export class TopLayer{
fieldName1: dataType;
fieldName2: Array<SecondLayer>;
}
export class SecondLayer{
fieldName1: datatype;
fieldName2: ThirdLayer;
}
export class ThirdLayer{
fieldName: datatype
}
another is: assign your json response to a var variable then access what you need:
e.g.
var x = response;
var list = x.list;
We can also do:
this.http.get("some-api-url")
.subscribe((response)=>{
for (let key in response) {
if (response.hasOwnProperty(key)) {
let element = response[key];
let singleData = {id: element.id, value: element.value};
this.dataArray.push(singleData);
}
}
},
(error)=>{
console.log(error)
});
When the response is like [{}, {}, ...]
Related
This is the JSON data i am fetching from POSTMAN. I want it to be ordered in a nearest to todays date. I tried many angular pipes but unfortunately nothings working. Any help would be great. I want to sort the date by the "broadcastOn" field. Thanks in advance.
[ {
"messageId": "09ca0609-bde7-4360-9d3f-04d6878f874c",
"broadcastOn": "2018-02-08T11:06:05.000Z",
"message": "{"title":"Server Side Test 2","text":"Different Message again","image":"https://api.adorable.io/avatars/285/abott#adorable.png","url":"https://www.google.co.in"}"
},
{
"messageId": "0a5b4d0c-051e-4955-bd33-4d40c65ce8f7",
"broadcastOn": "2018-02-08T10:36:27.000Z",
"message": "{"title":"Broadcast","text":"Broadcast","image":"https://api.adorable.io/avatars/285/abott#adorable.png","url":"https://www.google.co.in"}"
},
{
"messageId": "0a98a3f3-aa30-4e82-825a-c8c7efcef741",
"broadcastOn": "2018-02-08T11:45:00.000Z",
"message": "{"title":"Me sending the message","text":"Me sending the message","image":"https://api.adorable.io/avatars/285/abott#adorable.png","url":"https://www.google.co.in"}"
},
{
"messageId": "0cb4e30f-756a-4730-a533-594ddcd45335",
"broadcastOn": "2018-02-08T11:01:57.000Z",
"message": "{"title":"Server Side Test","text":"Different Message","image":"https://api.adorable.io/avatars/285/abott#adorable.png","url":"https://www.google.co.in"}"
}
]
Im adding a snippet from the service section as well for your reference..
addMessage(message) {
let header: Headers = new Headers();
header.append('Authorization', 'bearer' + this.authservice.getAccessToken());
let options = new RequestOptions({headers: header});
this.sent.push(message);
return this.http.post('https://sexhops8j5.execute-api.us-west-2.amazonaws.com/dev/notifications/broadcast', message, options)
.map(response =>
{
return response.json();
});
}
getMessage(){
let header: Headers = new Headers();
header.append('Authorization', 'bearer' + this.authservice.getAccessToken());
let options = new RequestOptions({headers: header});
return this.http.get('https://sexhops8j5.execute-api.us-west-2.amazonaws.com/dev/notifications/sent', options)
.map(response => {
let message=[];
for(let item of response.json()){
let parsedMessages = JSON.parse(item.message);
message.push({...parsedMessages, BroadcastOn: item.broadcastOn,MessageId: item.messageId});
}
console.log(message);
return message;
});
}
I'm adding a snippet of the .ts file as well
sendMessage(form){
this.messageService.addMessage({message:this.form.value.string, title:this.form.value.titleText, url:this.form.value.imageurl, image:this.form.value.image, broadcastOn:this.date})
.subscribe(message => { this.getSentMessages();console.log(message);}
);
this.message = '';
this.inputImage='';
this.inputTitle='';
this.inputString='';
this.inputUrl='';
}
getSentMessages(){
this.messageService.getMessage()
.subscribe(message => {this.sentMessages = message});
}
It's not necessary lodash, nor moment. broadcastOn is a string. The date is yyy-mm-ddTHH:mm, so, if a date is bigger that other, the string is bigger that other
getSentMessages(){
this.messageService.getMessage()
.subscribe(message => {
this.sentMessages = message.sort((a,b)=>{
return a.broadcastOn==b.broadcastOn?0
:a.broadcastOn>b.broadcastOn?1:-1
}));
});
}
With help of lodash and moment you can do it like this :
var sortedMessages = _.sortBy(messages, function(o) { return
moment(o.broadcastOn);
}).reverse();
//OR (With ES6 way)
var sortedMessages = _.sortBy(messages,(o) => moment(o.broadcastOn) ).reverse();
WORKING DEMO (Angular 5)
var messages = [ {
"messageId": "09ca0609-bde7-4360-9d3f-04d6878f874c",
"broadcastOn": "2018-02-08T11:06:05.000Z",
"message": {"title":"Server Side Test 2","text":"Different Message again","image":"https://api.adorable.io/avatars/285/abott#adorable.png","url":"https://www.google.co.in"}
},
{
"messageId": "0a5b4d0c-051e-4955-bd33-4d40c65ce8f7",
"broadcastOn": "2018-02-08T10:36:27.000Z",
"message": {"title":"Broadcast","text":"Broadcast","image":"https://api.adorable.io/avatars/285/abott#adorable.png","url":"https://www.google.co.in"}
},
{
"messageId": "0a98a3f3-aa30-4e82-825a-c8c7efcef741",
"broadcastOn": "2018-02-08T11:45:00.000Z",
"message": {"title":"Me sending the message","text":"Me sending the message","image":"https://api.adorable.io/avatars/285/abott#adorable.png","url":"https://www.google.co.in"}
},
{
"messageId": "0cb4e30f-756a-4730-a533-594ddcd45335",
"broadcastOn": "2018-02-08T11:01:57.000Z",
"message": {"title":"Server Side Test","text":"Different Message","image":"https://api.adorable.io/avatars/285/abott#adorable.png","url":"https://www.google.co.in"}
}
]
var sortedMessages = _.sortBy(messages, function(o) { return moment(o.broadcastOn); })
.reverse();
console.log(sortedMessages);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.20.1/moment.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.core.js"></script>
I am building a website over a database of music tracks. The database is as follows :
music table contains musicid and title
musicrights table contains musicid and memberid
members table contains memberid and memberinfo.
I'm trying to build an array of objects in my database service, which each entry represents a track containing its rightholders (contains information aubout one rightholder but not his name) and their member info (contains name etc). The backend is sailsjs and the code is as follows :
angular.module("myapp").service("database", ["$q", "$http", function($q, $http) {
var database = {};
function getHolderMember(rightHolder) {
return ($http.get("/api/members?where=" + JSON.stringify({
memberid: rightHolder.memberid
})).then(function (res) {
rightHolder.member = res.data[0];
return (rightHolder);
}));
}
function getRightHolders(doc) {
return ($http.get("/api/musicrights?where=" + JSON.stringify({
musicid: doc.musicid
})).then(function(res) {
// array of promises :
// each rightholder of a document has to solve member info
var rightHolders = [];
for (var i in res.data) {
var rightHolder = {
member: res.data[i].memberid,
type: res.data[i].membertype,
rights: res.data[i].memberrights
};
rightHolders.push(getHolderMember(rightHolder));
}
return ($q.all(rightHolders));
}).then(function(rightHolders) {
// expected array of one or two rightholders,
// enriched with member information
// actually returns array of one or two arrays of 30 members
// without rightholder info
console.log(rightHolders);
doc.rightHolders = rightHolders;
return (doc);
}));
}
database.music = function(q) {
return ($http.get("/api/music?where=" + JSON.stringify({
or: [{
title: {
contains: q
}
}, {
subtitle: {
contains: q
}
}]
})).then(function(res) {
// array of 30 promises :
// each one of 30 documents has to resolve its rightholders
var documents = [];
for (var i in res.data) {
documents.push(getRightHolders(res.data[i]));
}
return ($q.all(documents));
}));
}
return (database);
}]);
The first array of promises seems to work as expected, but not the second one in getRightHolders. What is strange is that this function returns an array of one or two promises, which are rightHolders waiting for their memberinfo. But in the callback where I console.log the response, i get an array of one or two (as per the number of pushed promises) but this array's elements are arrays of 30 memberinfo instead of one memberinfo. I don't understand how this $q.all() call gets mixed with the previous-level $q.all.
The data structure is roughly like this
documents [ ] ($http => 30 responses)
music.musicid
music.rightHolders [ ] ($http => 1, 2, 3 responses)
rightholder.rights
rightholder.member ($http => 1 response)
member.memberinfo
Any help appreciated. Thank you !
UPDATE : Thank you for your answer, it worked like a charm. Here's the updated code, with also the migrate service which formats data differently (there is some database migration going on). I kept it out of the first example but your answer gave me this neat syntax.
angular.module("myApp").service("database", ["$q", "$http", "migrate", function($q, $http, migrate) {
var database = {};
function getHolderMember(rightHolder) {
return ($http.get("/api/members?where=" + JSON.stringify({
memberID: rightHolder.member
})).then(function(res) {
return (migrate.member(res.data[0]));
}).then(function(member) {
rightHolder.member = member;
return (rightHolder);
}));
}
function getRightHolders(doc) {
return ($http.get("/api/rightHolders?where=" + JSON.stringify({
musicID: doc.musicID
})).then(function(res) {
return (
$q.all(res.data
.map(migrate.rightHolder)
.map(getHolderMember)
)
);
}).then(function(rightHolders) {
doc.rightHolders = rightHolders;
return (doc);
}));
}
database.music = function(q) {
return ($http.get("/api/music?where=" + JSON.stringify({
or: [{
title: {
contains: q
}
},
{
subtitle: {
contains: q
}
}
]
})).then(function(res) {
return (
$q.all(res.data
.map(migrate.music)
.map(getRightHolders)
)
);
}));
}
return (database);
}
I'm not quite sure how you're getting the result you describe, but your logic is more convoluted than it needs to be and I think this might be leading to the issues you're seeing. You're giving the getRightsHolders function the responsibility of returning the document and based on your comment above, it sounds like you previously had the getHolderMember() function doing something similar and then stopped doing that.
We can clean this up by having each function be responsible for the entities it's handling and by using .map() instead of for (please don't use for..in with arrays).
Please give this a try:
angular
.module("myapp")
.service("database", ["$q", "$http", function($q, $http) {
var database = {};
function getHolderMember(memberId) {
var query = JSON.stringify({ memberid: memberid });
return $http.get("/api/members?where=" + query)
.then(function (res) {
return res.data[0];
});
}
function populateRightsHolderWithMember(rightsHolder) {
return getHolderMember(rightsHolder.memberid)
.then(function (member) {
rightsHolder.member = member;
return rightsHolder;
});
}
function getRightHolders(doc) {
var query = JSON.stringify({ musicid: doc.musicid });
return $http.get("/api/musicrights?where=" + query)
.then(function(res) {
return $q.all(res.data.map(populateRightsHolderWithMember));
});
}
function populateDocumentWithRightsHolders(document) {
return getRightsHolders(document)
.then(function(rightsHolders) {
document.rightsHolders = rightsHolders;
return document;
});
}
database.music = function(q) {
return $http.get("/api/music?where=" + JSON.stringify({
or: [{
title: {
contains: q
}
}, {
subtitle: {
contains: q
}
}]
})).then(function(res) {
return $q.all(res.data.map(populateDocumentWithRightsHolders));
});
}
return (database);
}]);
I have a JSON response which contains an array of data.
$scope.Load = function () {
$http.post(elasticSearchURL, { "aggs": { "By_type": { "terms": { "field": "Name" }, "aggs": { "By_color": { "terms": { "field": "Color" } } } } } }).
then(function (response) {
$scope.modelList = response;
}, function (response) {
});
}
I would like to display the count of each element in the JSON.
MyHtml Code
<div ng-repeat="fruits in modelList.data.hits.hits | unique : '_source.fruitsName' | orderBy:'_source.fruitsName' ">
{fruits._source.name.length}
</div>
My Json data will be like this
{"_id":"e-AB2","_version":1,"found":true, "_source":{"name":"Apple", "color":"red"}}},
{"_id":"e-AB2","_version":1,"found":true, "_source":{"name":"Apple", "color":"red"}}},
{"_id":"e-AB2","_version":1,"found":true, "_source":{"name":"Apple", "color":"red"}}}
It displays only the length of the fruitname "Apple" length:5. I want to display the array length of _source.name
I have tried {{$index.length}} but it showing the count as 1 since I am using "unique:" in the <div>
How it can be achieved in angularjs.
Thanks in advance
I think the easiest approach is create hashmap that contains the counts:
$scope.counts = {};
$http.post(elasticSearchURL, postData).then(function (response) {
$scope.modelList = response.data;
response.data.forEach(function (item) {
var source = item._source.name;
if (!$scope.counts.hasOwnProperty(source)) {
$scope.counts[source] = 0;
}
$scope.counts[source]++;
});
});
Then in the view you can use:
Count = {{counts[fruits._source.name]}}
$scope.counts will look like:
{ 'Apple':3, 'Orange':5}
What you probably want to do is map all the data to a different array in this same fashion and get rid of the unique filter since there is no way to do what you are asking directly in the view
I have been googleing this for a few weeks with no real resolution.
I am sure someone will mark this a duplicate, but I am not sure it really is, maybe I am just being too specific, anyway here goes.
I am using angular in a node-webkit app that I am building. I have an api built in express and I am using MongoDB (#mongolab) with Mongoose for the DB.
I had this working fine as long as all of the data types were simple strings and numbers. but I had to restructure the data to use arrays and complex objects. After restructuring the data I was able to get post API calls to work fine, but I cannot get my PUT calls to work at all.
The data looks like this:
itemRoles was an array, but I thought it was throwing the error I am getting now, so I converted it back to a string.
itemStats is causing the problem. Angular is looking for an object, but itemStats is an array (I think anyway). itemStats used to be a string as well, but its easier to work with in my view if it is an array of objects with key:value pairs, which is why I altered it.
I should note I am new to MongoDB as well, first time using it.
{
"_id": {
"$oid": "55a10b9c7bb9ac5832d88bd8"
},
"itemRoles": "healer,dps",
"itemRating": 192,
"itemName": "Advanced Resolve Armoring 37",
"itemClass": "consular",
"itemLevel": 69,
"itemStats": [
{
"name": "Endurance",
"value": 104,
"_id": {
"$oid": "55a10b9c7bb9ac5832d88bda"
}
},
{
"name": "Willpower",
"value": 124,
"_id": {
"$oid": "55a10b9c7bb9ac5832d88bd9"
}
}
],
"__v": 0
}
The Mongoose Schema looks like this:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
//var stats = new Schema({
//name: String,
//value: Number
//});
var armoringSchema = new Schema({
itemType: String,
itemClass: String,
itemRoles: String,
itemLevel: Number,
itemName: String,
itemRating: Number,
itemStats: [{ name:String, value:Number}]
});
module.exports = mongoose.model('Armor', armoringSchema);
Express API Route:
/ on routes that end in /armors/:id
// ----------------------------------------------------
router.route('/armors/:id')
// get method omitted
// update the armoring with specified id (accessed at PUT http://localhost:8080/api/armors/:id)
.put(function(req, res) {
// use our armor model to find the armor we want
Armoring.findById({_id: req.params.id}, function(err, armor) {
if (err) {
return res.send(err);
}
for(prop in req.body) {
armor[prop] = req.body[prop];
}
// save the armor
armor.save(function(err) {
if (err) {
return res.send(err);
}
res.json({success:true, message: 'Armor updated!' });
});
});
})
Resource Factory:
swtorGear.factory('armoringFactory', ['$resource', function ($resource) {
return $resource('http://localhost:8080/api/armors/:id', {}, {
update: { method: 'PUT', params: {id: '#_id'}},
delete: { method: 'DELETE', headers: {'Content-type': 'application/json'}, params: {id: '#_id'}}
});
}]);
Route for editing:
.when('/edit/armor/id/:id', {
templateUrl: 'views/modelViews/newArmor.html',
controller: 'editArmorCtrl',
resolve: {
armoring: ['$route', 'armoringFactory', function($route, armoringFactory){
return armoringFactory.get({ id: $route.current.params.id}).$promise;
}]
}
})
Contoller (just the save method, the first part of the controller populates the form with existing data):
$scope.save = function(id) {
$scope.armor.itemStats = [
$scope.armor.stats1,
$scope.armor.stats2
];
$scope.armor.itemRoles = '';
if($scope.armor.role.tank) {
$scope.armor.itemRoles += 'tank';
}
if($scope.armor.role.healer) {
if($scope.armor.itemRoles != '') {
$scope.armor.itemRoles += ',healer';
} else {
$scope.armor.itemRoles += 'healer';
}
}
if($scope.armor.role.dps) {
if($scope.armor.itemRoles != '') {
$scope.armor.itemRoles += ',dps';
} else {
$scope.armor.itemRoles += 'dps';
}
}
console.log($scope.armor);
$scope.armor.$update(id)
.then(function(resp) {
if(resp.success) {
var message = resp.message;
Flash.create('success', message, 'item-success');
$scope.armors = armoringFactory.query();
} else {
var message = resp.message;
Flash.create('success', message, 'item-success');
}
});
}
Formatted data being sent via PUT method (from console.log($scope.armor) ):
Error on save:
I haven't seen nesting schemas in the way that you're doing it. Here's something to try (hard to say if this is it for sure, there's a lot going on):
var armoringSchema = new Schema({
itemType: String,
itemClass: String,
itemRoles: String,
itemLevel: Number,
itemName: String,
itemRating: Number,
itemStats: [{
name: String,
value: Number
}]
});
Also we need to pass in an object to $update instead of just a number. Change $scope.armor.$update(id) to $scope.armor.$update({id: id}).
I have an issue with loading remote data in multiple select2. My code is
var fetchGroups = function (queryParams) {
console.log(JSON.stringify(queryParams));
return $http.get("https://******/****/***/" + queryParams.data.query).then(queryParams.success);
};
$scope.groupSelectOptions= {
minimumInputLength: 3,
ajax: {
data: function (term, page) {
return { query: term };
},
quietMillis: 500,
transport: fetchGroups,
results: function (data, page) {
console.log(data);
// parse the results into the format expected by Select2 return { results: data };
var drastics = data.data.result;
if(drastics){
var data = new Array();
for(var i = 0; i < drastics.length; i++){
data.push(
{
id: drastics[i].id,
text: drastics[i].name
}
);
}
} else {
data = data.data.result;
}
return { results: data };
}
}
};
It returns the values from the get request but when i select it returns undefined at the input box.
Just make sure you've included the 'data' property to the $scope.groupSelectOptions like so :
$scope.groupSelectOptions= {
minimumInputLength: 3,
ajax: {
data: function (term, page) {
return { query: term };
},
.....
data:[]}
You should now see the term selected in the input field.