Possibility of passing propertie's names as arguments when constructing them - javascript-objects

I'm new to Javascript and need to build a function that produces arrays with objects inside to serve data to charts in react.
I want to pass the properties name as a string through an argument to that function. How does this work? I tried out a lot and cannot find an answer online. Sorry for this silly question.
See a simple example code below:
var datakeyelement = "Existing Volume";
var datakeyxaxis = "name";
var datax1 = "Business Clients";
var datae1 = 45;
var datax2 = "Private Clients";
var datae2 = 35;
function chartDataGenerator(
datakeyxaxis,
datakeyelement,
datax1,
datae1,
datax2,
datae2
) {
data = [
{
datakeyxaxis: datax1,
datakeyelement: datae1
},
{
datakeyxaxis: datax2,
datakeyelement: datae2
}
];
return console.log(data);
}
chartDataGenerator(
datakeyxaxis,
datakeyelement,
datax1,
datae1,
datax2,
datae2
);
So the built array with the two object shouldlook like :
[
{
name: Business Clients,
Existing Volume: 45
},
{
name: Private Clients,
Existing Volume: 35
}
]

Basically the only issue I see here is that you need computed prop names
function chartDataGenerator(
datakeyxaxis,
datakeyelement,
datax1,
datae1,
datax2,
datae2
) {
data = [
{
[datakeyxaxis]: datax1,
[datakeyelement]: datae1
},
{
[datakeyxaxis]: datax2,
[datakeyelement]: datae2
}
];
return console.log(data);
}

Related

Angular 5 display result from JSON response

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 [{}, {}, ...]

Angularjs specific routing

Ok my fellow friends and associates,
I am trying to display only information based off of a url: parameter,
I have a service that has save a ton of data so I can use it across my application, but the problem I am having is displaying the data that I want to show based off of my parameter.
so here is my route, I am sending my id based off an link attribute
/CourseMaterials/:ID"
I have my service which stores all of my json objects to use accross the app.
angular.module('app').service('SaveService', function () {
this.textExpress = {};
this.courseMaterials = {};
this.courses = {};
this.student = {};
this.receipts = {};
this.webOrders = {};
return {
//This saves the textExpress object to reuse
getTextExpress: function () {
return this.textExpress;
},
setTextExpress: function (t) {
this.textExpress = t;
},
//This saves the courseMaterials object
getCourseMaterials: function () {
return this.courseMaterials;
},
setCourseMaterials: function (cm) {
this.courseMaterials = cm;
},
//This saves the courses object
get
Courses: function () {
return this.courses;
},
setCourses: function (c) {
this.courses = c;
},
//This saves the student object
getStudent: function () {
return this.student;
},
setStudent: function (s) {
this.student = s;
},
//This saves the receipts object
getReceipts: function () {
return this.receipts;
},
setReceipts: function (r) {
this.receipts = r;
},
//This saves the webOrders object
getWebOrders: function () {
return this.webOrders;
},
setWebOrders: function (wo) {
this.webOrders = wo;
},
}
});
I am a little stumped at how to say to my controller of my new view display only this info from my service
CourseMaterials/:id
So an object I might have looks like this
CourseMaterials[0] {
course: cit298,
author: ben stein,
isbn: xxxxxxxxxxxxxx,
}
CourseMaterials[1] {
course: cit298,
author: george stein,
isbn: xxxxxxxxxxxxxx,
}
On my new page I want to display something based off of the course applicable to what a user has selected based of the params in the link.
That looks like
http://localhost:55436/#!/CourseMaterials/cit%20298 etc......

angular chaining arrays of promises

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);
}]);

MEAN stack - How do I retrieve a data subset based on user?

I'm retrieving datapoints by mongoose from a collection of the form:
{
"_id":"1",
"creator":
{"_id":"a",
"username":"aaa",
"name":"aaa"},
"comment":"",
"value":10,
"created":"2016-05-28T12:09:25.666Z"},
{
"_id":"2",
"creator":
{"_id":"b",
"username":"bbb",
"name":"bbb"},
"comment":"",
"value":100,
"created":"2016-05-28T09:13:18.361Z"}
...
Where each datapoint is defined by a Schema and creator is defined by a separate Schema.
I'm able to retrieve all datapoints via angular by using the resource query method:
$scope.find = function() {
$scope.datapoints = Datapoints.query();
};
I would now like to retrieve only those datapoints corresponding to the specific user (whose details are accessible through $scope.authentication.user).
Failed attempts include:
$scope.findByUser = function() {
user = $scope.authentication.user;
$scope.datapoints = Datapoints.query({creator:user});
};
or:
$scope.findByUser = function() {
Datapoints.query(function(result) {
$scope.datapoints = $filter('filter')(result, {creator: $scope.authentication.user});
});
or:
$scope.findByUser = function() {
$scope.datapoints = Datapoints.query();
$scope.datapoints = $filter('filter')($scope.datapoint, {creator: $scope.authentication.user});
};
Any help is appreciated. Thanks!!

AngularJS. Return new factory instance

I'm a newbie in AngularJS and have faced the issue.
Can I reinject my factory singleton object across all controllers, where it's been injected?
For example:
.factory('medicalCenterService', function(MedicalCenterResource) {
var medicalCenterService = {};
medicalCenterService.currentMedCenter = MedicalCenterResource.get();
medicalCenterService.reloadMedCenter = function() {
medicalCenterService.currentMedCenter = MedicalCenterResource.get();
return medicalCenterService.currentMedCenter;
};
medicalCenterService.updateMedicalCenter = function(medicalCenter) {
MedicalCenterResource.updateMedicalCenter(medicalCenter);
medicalCenterService.currentMedCenter = medicalCenter;
};
return medicalCenterService;
})
In MedicalCenterController I get singleton object with medical center when application starts:
function MedicalCenterController($scope, medicalCenterService) {
$scope.currentMedCenter = medicalCenterService.currentMedCenter;
}
But later I try to edit medical center fields (name, address, etc..) in AccountProfileController
function AccountProfileController($scope, medicalCenterService) {
$scope.currentMedCenter = medicalCenterService.currentMedCenter;
$scope.applyMedCenterChanges = function (currentMedCenter) {
medicalCenterService.updateMedicalCenter(currentMedCenter);
};
}
And what I'm expecting to have is the object with updated fields.
How to return a new instance of my singleton?
Do you want something like this?
.factory('MedicalCenter', function(MedicalCenterResource) {
var MedicalCenter = function () {
var center = MedicalCenterResource.get(),
update = function() {
MedicalCenterResource.updateMedicalCenter(center)
};
return {
center: center,
update: update
}
};
return MedicalCenter;
})
function MedicalCenterController($scope, MedicalCenter) {
center = new MedicalCenter();
$scope.currentMedCenter = center.center;
}
function AccountProfileController($scope, MedicalCenter) {
center = new MedicalCenter();
$scope.currentMedCenter = center.center;
$scope.applyMedCenterChanges = function () {
center.update();
};
}
Like you wrote in post services are Singletons and its good way to share data over services. However if you want to create new instance of factory/service, you can't do that but we can create list of objects in one service/factory where each list item represents different instance. Something like:
.factory('medicalCenterService', function(MedicalCenterResource) {
var medicalCenterServices = [
{ctrlName: 'MedicalCenterController',medicalCenterService: {/*....*/}},
{ctrlName: 'AccountProfileController',medicalCenterService: {/*....*/}},
];
//......
})

Resources