Angular ngbTypeahead gives [Object] error - html

My component.html (Input field)
<input type="text" class="form-control" [(ngModel)]="searchQuery" [ngbTypeahead]="recommends"
name="searchQuery" typeaheadOptionField="username">
My component.ts
this.recommends = (text$: Observable<string>) => {
return text$.pipe(
debounceTime(200),
distinctUntilChanged(),
switchMap((searchText) => this.stats.getSearchCompletion(searchText))
);
}
My getSearchCompletion function
getSearchCompletion(searchQuery) {
if(searchQuery) return this.http.post(backendURL + '/my/route', { searchQuery: searchQuery }, { headers: this.headers }).pipe(map(res => res.json()));
}
The repsonse is returned in a format like this:
[{
"username": "test"
},
{
"username": "test2"
}]
I get the following error:
To Image
I guess it is because my server response has multiple objects inside a list. But how do I bind the ngbTypeahead to for example username? I tried typeaheadOptionField="username" which gives me the error. The list pops up but has no entries.

You can use some of javascript skills to convert the response into plain array of strings, something like this
if(searchQuery) return this.http.post(backendURL + '/my/route', { searchQuery: searchQuery }, { headers: this.headers }).pipe(map(res => {
let arr:string[] = [];
res.json().forEach(x=>{
arr.push(x['username']);
});
return arr;
}));
This is based on assumption that your api response is in this format
[{ "username": "test"},{ "username": "test2"}]
Which is an array of objects.
Thanks.

Related

Access String array in Json

The API I am using has a nested string array it seems, I need to extract the path from it, but I cannot figure out how....
This is a break down of what I need to access.
the productimage is wrapped in quotes...
[
{title: "Item 1",
productimage: "[{"1":{"size":"75x75","path":"/10000/img.jpg"}]"
},
{title: "Item 2",
productimage: "[{"1":{"size":"75x75","path":"/20000/img.jpg"}]"
}
]
I am trying to access the image path...
The problem seems to be reading the string, I have attempted to treat it like an array, and a string and get mixed results..
Edited:
here is the entire productimages object, it is coming from an apache database that i have no control over.
productimages: "[{"1":{"size":"75x75","path":"/100000/101819-75x75-A.jpg"}},{"2":{"size":"222x222","path":"/100000/101819-600x600-A.jpg"}},{"3":{"size":"328x328","path":"/100000/101819-600x600-A.jpg"}}]"
my current axios call looks like this.
async function handleSubmit(searchData) {
if (searchData) {
const payload = searchData;
try {
const response = await axios({
url: `${baseUrl}q=*:*&fq=title:${payload}&fq=storeid:1234
method: "get",
});
//Set Hook
setData(response.data.response.docs);
} catch (error) {
console.error(error);
}
}
}
Here is the response data that is being set..
{productid: 1234, itemups: 1234, title: "productname", productimages: "[{"1":{"size":"75x75","path":"/100000/101819-75x75-A.jpg"}},{"2":{"size":"222x222","path":"/100000/101819-600x600-A.jpg"}},{"3":{"size":"328x328","path":"/100000/101819-600x600-A.jpg"}}]", productcount: 7}
I can get everything out of this, except the image.
You've to parse productimage:
const parsedArray = array.map(obj => {
let path = '';
try {
const productimage = JSON.parse(`${obj.productimage}`);
path = productimage[0].path
} catch(err) {
console.error(err)
}
return { ...obj, path }
});
[EDIT]
Axios response:
axios() // some axios call
.then(res => res.data)
.then(array => {
// ... here you can transform your array
})
Also make sure your json is properly formatted.
{
[
{"title": "Item 1",
"productimage": "[{"1":{"size":"75x75","path":"/10000/img.jpg"}]"
]
}

React JS - How do I pass variables (parameters) to the API URL?

I have a single page that consist of two dropdown-list components; The page is only accessible upon successful authentication (valid token). Both dropdown-list consumes it's data from different JSON-API's. I have one of the dropdown list functional, but for the other, the URL to it's API requires parameters.
Example URL:
http://buildingsAPI:111/api/buildings/
tested via postman with an id appended:
http://buildingsAPI:111/api/buildings/abcde-abce-abc2-111-2222
sample Json:
[
{
"abc_buildingid": "1111-2222-3333-aaa-1111117",
"abc_energyprogramid": "abcde-abce-abc2-111-2222",
"siteName": "Building 1",
"Available": false,
"clientName": "Client 1"
},
{
"abc_buildingid": "222-2222-3333-aaa-1111117",
"abc_energyprogramid": "xyz11-abce-abc2-111-2222",
"siteName": "Building 2",
"Available": false,
"clientName": "Client 2"
},
]
...am already obtaining the token upon user authentication (localStorage), but I also need to append/pass the abc_energyprogramid as a parameter to the API URL.
...the code:
constructor(props) {
super(props);
this.getToken = this.getToken.bind(this);
}
componentDidMount() {
const bearerToken = this.getToken();
fetch('http://buildingsAPI:111/api/buildings/?myparam1={abc_energyprogramid}', {
method: 'GET',
headers: {
'Content-type': 'application/json',
'Authorization': `Bearer ${bearerToken}`
},
})
.then(results => results.json())
.then(buildings => this.setState({ buildings: buildings }))
}
getToken() {
return localStorage.getItem('id_token');
}
render() {
console.log(this.state.buildings);
return(
<div>
<select className="custom-select" id="siteName">
{ this.state.buildings.map(item =>(
<option key={item.siteName}>{item.siteName}</option>
))
}
</select>
</div>
);
}
...I currently get an error:" Unhandled Rejection (SyntaxError):unexpected end of JSON input" on this line of the code: .then(results => results.json()). Could I get some help with this please?
I think the problem is the way you're referencing abc_energyprogramid
Change this:
fetch('http://buildingsAPI:111/api/buildings/?myparam1={abc_energyprogramid}')
to:
fetch(`http://buildingsAPI:111/api/buildings/?myparam1=${abc_energyprogramid}`)
Notice the back-ticks and ES6 template string literal.

Saving data from JSON to object

I have a problem with pushing data from json to object.
This solution works for me but I am not happy with it. Look at the service.
Is there better way to save data from this json to object?
The json that i get from server looks like this:
{"documents": {"document": [
{
"id": 1,
"description": "Lorem ipsum",
"date": "2017-03-01"
},{
"id": 2,
"description": "Lorem ipsum",
"date": "2017-04-01"
}
]}}
My service:
downloadDocuments(id: number): Observable<DocumentsDTO[]>{
let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Authorization', this.authorizationService.basic);
let options = new RequestOptions({headers: headers});
let body = JSON.stringify(id);
return this.http
.post(DOCUMENTS_URL, body, options)
.map((response) => response.json().documents.document)
}
And component where I call this service:
documentsArray: Array<DocumentsDTO>;
downloadUserDocuments(id: number) {
this.documentsService.downloadDocuments(id)
.subscribe(documents =>{
if(documents !=null){
this.documentsArray = [];
documents.forEach((data) => {
this.documentsArray.push(data);
});
}
});
}
This solution works for me but I am not happy with .
Is there better way to save data from this json to array?
Service
return this.http
.post(DOCUMENTS_URL, body, options)
.map((res: Response) => {
res.json().map((obj) => {
new Document(obj.id, obj.description, obj.date)
})
})
This should return a collection of Documents
I'm not seeing how you could get past
.map((response) => response.json().documents.document)
This is just where your array is placed inside the response, period. You'd have to make changes to backend to change this.
What I am not understanding is why you are doing unnecessary iteration inside your subscribe, why not directly assign the array that is coming to your documentsArray? Like so:
this.documentsService.downloadDocuments(id)
.subscribe(documents => {
if(documents != null) {
this.documentsArray = documents;
}
});

Accessing JSON object properties directly and log it

I'm trying to access JSON Object properties directly and log it, here is my function :
loadProcesses(filter?){
this._postService.getAllProcess(filter)
.subscribe(
res=> {
this.processListe = res;
// console.log(this.processListe.)
}
,null,
() =>{
console.log("get processes liste" + filter)
});
So this.processListe contain a JSON Object, and my JSON format is like this:
{"Person": {
"id": "A256",
"name": "GET",
"status": "active",
"description": "hardworking, openminded",
...
So it will contains exactly the same things, for example if i want to simply print the label on a console log how can i do it ??
Are you looking for something like this:
function parseObject(obj)
{
for(var key in obj)
{
console.log("key: " + key + ", value: " + obj[key])
if(obj[key] instanceof Object)
{
parseObject(obj[key]);
}
}
}
just call parseObject(res) in the subscribe method.
parse it and access the fields.
var obj = JSON.parse(filter);
obj.Person.id;
//etc
parse it in the .subscribe:
res => this.processListe = res.json();
a better solution is to declare your response with any :
loadProcesses(filter?){
this._postService.getAllProcess(filter)
.subscribe(
(res: any)=> {
this.processListe = res;
// console.log(this.processListe.)
}
,null,
() =>{
console.log("get processes liste" + filter)
});
this way you can access any attirbute in your response

RESTAdapter and JSON without root

The json I get from the API looks like this:
[
{
"id": "1",
"title": "title1"
},
{
"id": "2",
"title": "title2"
},
]
Unfortunately I can't change the API, so how do I get it to work with the RESTAdapter?
I tried with this code from this post :
App.ApplicationSerializer = DS.RESTSerializer.extend({
normalizePayload: function(type, payload) {
return { posts: payload };
}
});
But I get the error " Error while loading route: Error: No model was found for 'post' ".
Which I don't understand.
This is my posts Route.
App.PostsRoute = Ember.Route.extend({
model: function() {
return this.store.find('posts');
}
});
You have a number of typeos here.
First since you are dealing with posts, it is probably best to use the PostSerializer.
App.PostSerializer = DS.RESTSerializer.extend({
normalizePayload: function(type, payload) {
return { posts: payload };
}
});
And when you are requesting models from the server, you want to use the model name, so you would use post (not posts).
App.PostsRoute = Ember.Route.extend({
model: function() {
return this.store.find('post');
}
});
Neither normalizePayload nor normalize is working for me. What I am doing is:
// app/serializers/application.js
import DS from 'ember-data';
export default DS.RESTSerializer.extend({
extractArray: function(store, type, payload) {
var payloadTemp = {}
payloadTemp[type.typeKey] = payload;
return this._super(store, type, payloadTemp);
},
extractSingle: function(store, type, payload, id) {
var payloadTemp = {}
payloadTemp[type.typeKey] = [payload];
return this._super(store, type, payloadTemp, id);
}
});