Angular HttpClient-subscribe select property from data - json

I'm really sure about, that this question is answered multiple times in here. But I can't find them/don't knwo which terms to search for.
I've got a JSON-file looking like that:
{
"pages": [{
"displayname": "PageA",
"url": "http://google.de",
"icon": "iconZ"
},
{
"displayname": "PageB",
"url": "http://www.pageb.co.uk",
"icon": "iconY"
}
],
"icons": [{
"alias": "iconZ",
"filename": "iconZ.svg"
},
{
"alias": "iconY",
"filename": "iconY.svg"
}
]
}
Now I'm using the HttpClient (here called httpService) to get the data from the file.
this.httpService.get('./assets/pageconfig.json').subscribe(
data => {
this.arrAdress = data as string[];
},
(err: HttpErrorResponse) => {
console.log(err.message);
}
);
I want to use the content of pages in my ngFor in the Frontend and I want to get an array of the icon-content for use in the Backend. How can I select/split the data by using the properties.
Thanks for your help
Elias

Considering your pageconfig.json is used in both front and backend, and that you just need the "pages" attribute in your angular app, you may get it this way:
this.httpService.get('./assets/pageconfig.json').subscribe(
data => {
this.arrAdress = data.pages;
},
(err: HttpErrorResponse) => {
console.log(err.message);
}
);
You don't need to cast the data type.
You could also use the rxjs observable map chaining to parse your data and get only what interests you:
import { map } from 'rxjs/operators';
this.httpService.get('./assets/pageconfig.json')
.pipe(map(data => data.pages))
.subscribe(pages=> {
this.arrAdress = pages;
}.catch((err: HttpErrorResponse) => {
console.log(err.message);
});
I hope this is what you were looking for.

Need to remove string[], instead use Array of object or any.
this.httpService.get('./assets/pageconfig.json').subscribe(
data => {
this.arrAdress = data;
},
(err: HttpErrorResponse) => {
console.log(err.message);
}
);
sendData(icon){
const matched = this.arrAdress.icons.filter(iconObj => iconObj.alias === icon);
console.log(matched);
}
**Template:**
<div *ngFor="let adress of arrAdress?.pages;" (click)="sendData(adress.icon)">
<span>{{adress.displayname}}</span>
</div>

You have two solutions here to solve this issue
Suppose httpClient.Delete() option returns back you an observable object with employeeId as property in it.
Solution 1 (example)
Create an local variable and assign data to it using let statement (e.g. let response: any = data;).
delete(employee: any) {
this.employeeService.deleteEmployee(employee.id)
.subscribe(
data => {
let response: any = data;
// now you can use response.employeeId
},
(error) => {
console.log(error)
},
() => {
console.log("The operation has been completed")
}
);
}
Solution 2 (example)
Assign type any (e.g. (data : any) to received response
delete(employee: any) {
this.employeeService.deleteEmployee(employee.id)
.subscribe(
(data: any) => {
// now you can use data.employeeId
},
(error) => {
console.log(error)
},
() => {
console.log("The operation has been completed")
}
);
}

Related

React JSON is undefined

I'm fetching this JSON from an API:
{
"data": {
"email": "test#tre.com",
"inserted_at": "2021-03-30T15:37:06",
"links": [
{
"id": 1,
"title": "My link title",
"url": "http://google.com"
},
{
"id": 2,
"title": "My Youube title",
"url": "http://youtube.com"
}
]
}
}
I'm fetching it this way using Hooks:
export default function Notes() {
const [json, setJSON] = useState([]);
useEffect(() => {
fetch("http://localhost:4000/api/users/1", {
method: "GET"
})
.then((response) => response.json())
.then((json) => {
// console.log(data);
setJSON(json);
})
.catch((err) => {
console.error(err);
});
}, [setJSON]);
Then I try to show it like this:
return (
<>
<div className="content">
{JSON.stringify(json)}
<h1>{json.email}</h1>
</div>
</>
);
The line {JSON.stringify(json)} shows the JSON.
But the line <h1>{json.email}</h1> doesn't show anything.
I don't know why that happens and how can I access my variables.
Thanks . I appreciate any help
Is the data in the form of an array or an object?
You defined the initial state as and array ad hence you cannot do
// you can't do json.email if you expect the response as and array
const [json, setJSON] = useState([]);
change it to
const [json, setJSON] = useState({});
if it is an object. Then in the template do
{json.data && <h1>{json.data.email}</h1>}
<h1>{json.data && json.data.email}</h1>
instead of
<h1>{json.email}</h1>

Retrieving data from MongoDB ánd MySQL simultaneously

I am trying to retrieve data from my MongoDB database which stores chat conversations. This works fine and returns what I want. However, I only save userIDs in MongoDB, so I need to query profile picture, username etc from my MySQL database. I tried the following:
app.get('/api/retrieveAllChats', (req, res) => {
var Conversation = mongoose.model('Conversation', ConversationSchema);
var ChatMessage = mongoose.model('Message', ChatMessageSchema);
var userID = req.query.userID.toString()
var members = []
var conversationData = []
var retrieveAllChats = new Promise(function(resolve, reject) {
Conversation.aggregate([{ $match: { "members.uID": userID } }, { $lookup: { foreignField: "c_ID", from: "messages", localField: "_id", as: "messages" } }, { "$unwind": "$messages" }, { "$sort": { "messages.t": -1 } }, { "$group": { "_id": "$_id", "lastMessage": { "$first": "$messages" }, "allFields": { "$first": "$$ROOT" } } }, { "$replaceRoot": { "newRoot": { "$mergeObjects": [ "$allFields", { "lastMessage": "$lastMessage" } ] } } }, { "$project": { "messages": 0 } }], function (err, conversations) {
if (err) return handleError(err);
conversations.forEach((conversation, i) => {
return new Promise(function (resolveConversations, rejectConversations) {
var membersPromise = conversation.members.forEach((member, x) => {
return new Promise(function (resolveUserData, rejectUserData) {
getUserData(member["uID"], function(userData) {
members.push({userID: member["uID"], joinDate: member["j"], userName: userData["userName"], userDisplayName: userData["userDisplayName"], userVerified: userData["userVerified"], userProfilePicURL: userData["userProfilePicURL"]})
console.log("userData: ", userData)
conversations[i].members[x].userData = userData
conversationData = conversations
resolveUserData({userID: member["uID"], joinDate: member["j"], userName: userData["userName"], userDisplayName: userData["userDisplayName"], userVerified: userData["userVerified"], userProfilePicURL: userData["userProfilePicURL"]})
})
})
})
resolveConversations()
})
})
resolve()
})
}).catch(error => {
console.log(error)
res.json({ errorCode: 500 })
})
retrieveAllChats.then(function() {
res.header("Content-Type",'application/json');
res.send(JSON.stringify(conversationData, null, 4));
})
})
However, the conversationData array is always empty. So I need a way to resolve the retrieveAllChats promise and pass the data I added to the existing conversations object to return it with all information I need. Any ideas on how I can do this? (getUserData is a function to retrieve the MySQL data, this one works fine and returns what I want)
You are trying to do async operation inside forEach which wouldn't work. You need to either use for...of or Promise.all.
Also, you can make this code much cimpler by using .exec() at the end of running any query or aggregation as that is supported by mongoose. Something like this should work. Make sure you change your routte line to this to tell it is an async function
app.get("/api/retrieveAllChats", async (req, res) => {
core logic
const conversions = await Conversation.aggregate([{"$match": {"members.uID": userID}}, {"$lookup": {"foreignField": "c_ID", "from": "messages", "localField": "_id", "as": "messages"}}, {"$unwind": "$messages"}, {"$sort": {"messages.t": -1}}, {"$group": {"_id": "$_id", "lastMessage": {"$first": "$messages"}, "allFields": {"$first": "$$ROOT"}}}, {"$replaceRoot": {"newRoot": {"$mergeObjects": ["$allFields", {"lastMessage": "$lastMessage"}]}}}, {"$project": {"messages": 0}}]);
for(const conversation of conversations) {
for(const member of conversation.members) {
// add your promise call here and either await it or use then to get the promise value.
}
}

Iterate through JSON object in angular 6

I am new to Angular and probably this might be a silly question. I am trying to get an api response and save it into an array. My API response looks like :
[
{
"name1": {
"name": "name1",
"api": {
//somedata
},
"t1p": {
//somedata
}
}
},
{
"name2": {
"name": "name2",
"api": {
//somedata
}
},
"t1p": {
//somedata
}
}
}
]
I get the response from the code
var data = [];
makeRequest(): void {
this.http
.get(this.URL1)
.subscribe((res: Response) => {
this.data = res;
console.log(this.data);
}, err => console.log(err));
}
Now I want to fetch the "name" value from each of the JSON object. I tried doing this:
var ids:string = [];
for(let result of this.data){
ids.push(result.name);
console.log("Added"+result.name);
}
But I am not able to achieve the same. Can anyone tell me what is wrong with the same.
You can implement it with .map and Object.keys()
const result = data.map(item => Object.keys(item)[0]);
console.log(result); // ['name1', 'name2']
If you want to perform that method to your http call. You can do so by:
this.http
.get(this.URL1)
.pipe(map(res => res.map(item => Object.keys(item)[0])))
.subscribe((res: Response) => {...});
Try this !
for(let i = 0; i < this.data.length; i++ )
{
for(let key of this.data[i])
{
if(this.data[i][key].hasOwnProperty("name"))
ids.push(this.data[i][key][name]);
}
}
As your object lies inside another object with key as name.
makeRequest(): void {
this.http
.get(this.URL1)
.pipe((response) => {
response.map((re,index)=> re['name'+(index+1)]['name'])
})
.subscribe((res: Response) => {
this.data = res;
console.log(this.data);
}, err => console.log(err));
}
I gave the solution by looking at your response API. Now in the subscriber, you will get the only name.

How to ignore a variable in JSON data in Angular TypeScript

I am facing a problem while reading a JSON file in angular 7.
below is the format of my JSON data file.
[
{
"attributes": {
"User": "jay"
}
},
{
"attributes": {
"User": "roy"
}
},
{
"attributes":{
"User": "kiya"
}
},
{
"attributes":{
"User": "gini"
}
},
{
"attributes": {
"User": "rock"
}
},
{
"attributes": {
"User": "joy"
}
}
]
here is my component.ts file method in which I am calling service for a JSON file.
this.rest.getUsers().subscribe((data: {}) => {
console.log(data);
this.items = data;
//this.items=data;
});
Here is my service.ts file method.
private extractData(res: Response) {
let body = res;
return body || { };
}
getUsers():Observable<any> {
return this.httpService.get('./assets/usersdetails.json').pipe(
map(this.extractData));
}
Now I want to read only User from the JSON file and I want to filter the word attributes. is there any way to filter this thing from JSON file, so that I can only get the User value. because in my Project this attributes in JSON is creating a problem and I want to ignore or filter this.
because in my application I need to read the JSON as below format.
[
{
"User": "jay"
},
{
"User": "roy"
},
{
"User": "kiya"
},
{
"User": "gini"
},
{
"User": "rock"
},
{
"User": "joy"
}
]
but the data is coming in the format as above mentioned JSON format with attributes
so is there any way to filter the extra attributes thing from the JSON at the time of reading.
You don't show the code for the extractData method, so it is hard to say what isn't working there, but you should be able to accomplish your goals with the following.
return this.httpService
.get('./assets/usersdetails.json')
.pipe(
map(data => data.map(d => d.attributes))
);
If there are other properties on 'attributes' and you really only want the 'user' data, then you could further update the code to:
return this.httpService
.get('./assets/usersdetails.json')
.pipe(
map(data => data.map(d => ({ 'User': d.attributes.User })))
);

Angular 5 Observable mapping to Json array

My backend return this :
{
"FirstResponse": [
{
"MyField1": "AAA",
"MyField2": "AAAAAAA"
},
{
"MyField1": "BBB",
"MyField2": "BBBBBBB"
},
{
"MyField1": "CCC",
"MyField2": "CCCCC"
}
],
"SecondResponse": [
{
"FirstName": "FirstNameA",
"LastName": "LastNameA"
},
{
"FirstName": "FirstNameB",
"LastName": "LastNameB"
}
]
}
I'd like map FirstReponse to a variable and SecondResponse to another variable.
How can I adapt the code below ?
search(): Observable<any> {
let apiURL = `......`;
return this.http.get(apiURL)
.map(res => res.json())
}
Update : Excepted result
In one variable this :
[
{
"MyField1": "AAA",
"MyField2": "AAAAAAA"
},
{
"MyField1": "BBB",
"MyField2": "BBBBBBB"
},
{
"MyField1": "CCC",
"MyField2": "CCCCC"
}
]
In a second :
[
{
"FirstName": "FirstNameA",
"LastName": "LastNameA"
},
{
"FirstName": "FirstNameB",
"LastName": "LastNameB"
}
]
You could create a new file which exports the model class and then assign it to the returning Observable type. Something like:
new model.ts file
class FieldModel {
Field1: string;
Field1: string;
}
export class valuesModel {
MyValues: Array<FieldModel>;
}
on the service.ts
import { valuesModel } from 'model';
search(): Observable<valuesModel> {
let apiURL = `https://jsonplaceholder.typicode.com/users`;
return this.http.get(apiURL)
.map(res => res.json())
}
Please check this approach, use
import { Http, Response} from '#angular/http';
import { Observable } from 'rxjs/Observable';
public search(){
let apiURL = `https://jsonplaceholder.typicode.com/users`;
return this.http.get(apiURL)
.map((res: Response)=> return res.json();)
.catch((error: Response) => {
return Observable.throw('Something went wrong');
});
}
for this search() method you can subscribe from your component.
And if you want to map output into respected modal then please provide format of same.So that i can help
I don't crealry understan what you wanna get because you not provide example result,
however try this - change line:
.map(res => res.json())
to
.map(res => res.json().MyValues )
using this you will get at the top level similar array like in link you provided in comment below you question: https://jsonplaceholder.typicode.com/users
UPDATE (after question update 9.10.2018)
Currently .map(res => res.json()) returns object that has two fields (variables) "FirstResponse" and "SecondResponse". You can have acces to it by for example (I write code from head):
public async loadData()
{
let data = await this.yourService.search().toPromise();
let firstVariable = data.FirstResponse;
let secondVariable = data.SecondResponse;
...
}
So as you describe in your question/comments in loadData() you get result in two variables as you want.
Or alternative answer - if you wanna do this inside search() then you can do that in such way for example:
search(): Observable<any> {
let apiURL = `......`;
return this.http.get(apiURL)
.map( (res) => {
let data = res.json();
return {
firstVariable: data.FirstResponse,
secondVariable: data.SecondResponse,
}
})
}