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);
}
});
Related
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.
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"}]"
]
}
Is it possible for angular2 to return raw json response? Ex.
Component
getrawJson(){
this.someservice.searchJson()
.subscribe( somelist => this.somelist = somelist,
error => this.errorMsg = <any>error);
}
For service
searchJson(num: number, somestring: string, somestring2: string): Observable<stringDataObj> {
let body = JSON.stringify({"someJsonData"[{num, somestring, somestring2}]});
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.post(URL, body, options)
.map(this.jsonObj)
.catch(this.handleError);
}
private jsonObj(res: Response) {
let body;
return body{ };
}
The above implementation returns Array . Will there be a way for me to get the raw json data returned by the service? I'm expecting to have json response like below
{
"dataParam": [ {
"num": "08",
"somestring": "2016-10-03",
"somestring2": "2016-10-03"
}],
"someDatalist": [ {
"one": "08",
"two": 1,
"three": "2016-10-03"
}]
}
Thanks!
Yes off course you can !!
Actually angualar2 returns Response in the form of Observable instead of promise Like in angular1.x , so in order to convert that observable into raw Json format we have to use the default method of angular2 i.e
res.json()
There are no of method apart from .json() provided by angular which can be described here for more info.
methods include
res.text()
res.status
res.statusText
etc
https://angular.io/docs/ts/latest/api/http/index/Response-class.html
update
use your code like this
return this.http.post(URL, body, options)
.map(res => {return res.json()})
.catch(this.handleError);
}
private jsonObj(res: Response) {
return res.json() || {} ;
}
Currently I have an issue with getting back a proper JSON object I'm fetching with Backbone fetch() and putting it into a Handlebars template.
See below my code, I have made a ugly workaround for now to test my Backend API
When converting to JSON with *.toJSON(), it just adds an extra object in-between and I don't need this extra object
Object [0]
--> books
----> Object [0]
------> Array of book
--------> book
--------> cities
JSON
{
"books": [
{
"book": 00001,
"cities": [
"TEST"
]
},
{
"book": 00002,
"cities": [
"TEST"
]
},
{
"book": 00003,
"cities": [
"TEST"
]
}
],
"more": true
}
JavaScript
var Book = Backbone.Model.extend({
default: {
book: 0,
cities: ["TEST1", "TEST2", "TEST3"]
},
url: function () {
return ".list.json";
}
});
var Books = Backbone.Collection.extend({
model: Book,
url: ".list.json"
});
var BooksView = Backbone.View.extend({
initialize: function(){
_.bindAll(this, 'render');
this.collection = new Books();
this.collection.fetch();
this.source = $('.e-books-template').html();
// Use an extern template
this.template = Handlebars.compile(this.source);
var self = this;
this.collection.fetch({
success: function () {
self.render();
},
error: function () {
console.log("ERROR IN BooksView");
}
});
},
render: function() {
var collect = JSON.stringify(this.collection);
collect = collect.slice(1, -1);
var html = this.template($.parseJSON(collect));
this.$el.html(html);
}
});
var booksView = new BooksView({ });
$(document).ready(function(){
booksView.$el = $('.e-books-content');
});
A Backbone collection expects an array of models but your JSON provides an object with the array under a books key. Parse the server response to format the data :
var Books = Backbone.Collection.extend({
model: Book,
url: ".list.json",
parse: function(data) {
return data.books;
}
});
Pass your data to your template via http://backbonejs.org/#Collection-toJSON ,
// directly as an array in your template
var html = this.template(this.collection.toJSON());
// under a books key
var html = this.template({
books: this.collection.toJSON()
});
And a demo http://jsfiddle.net/nikoshr/8jdb13jg/
[EDIT] Answered [/EDIT]
I've just started with Backbone, and have run into a stumbling block that I can't figure out.
I have the following collection which sends a request to JSON-API on my site to fetch posts by category:
Posts.Collections.CategoryPosts = Backbone.Collection.extend({
initialize: function(options) {
this.id = options.id;
var intRegex = /^\d+$/;
if(intRegex.test(this.id)) {
this.url_querystring = '?id=' + this.id;
}
else {
this.url_querystring = '?slug=' + this.id;
}
},
url: function() {
return '/api/core/get_category_posts/' + this.url_querystring;
},
model: Posts.Models.CategoryPost
});
Now, this works the charm; but the problem is; the JSON for this return is actually:
{
"status": "ok",
"count": 10,
"count_total": 79,
"pages": 7,
"category": { ... }
"posts": [
{ ... },
{ ... },
...
]
}
So, when my code that uses fetch() on the collection tries to assign the return to the individual Post models; it only creates one.
How do I tell Backbone that the models should be created using the "post" sub-object in the JSON return? There really doesn't seem to be a whole lot about this out there; or I don't know exactly what to search for?
Any help would be great - preferably a push in the right direction, rather than giving the answer.
The answer was in defining a parse function to the collection:
Posts.Collections.CategoryPosts = Backbone.Collection.extend({
initialize: function(options) {
this.id = options.id;
var intRegex = /^\d+$/;
if(intRegex.test(this.id)) {
this.url_querystring = '?id=' + this.id;
}
else {
this.url_querystring = '?slug=' + this.id;
}
},
// Make sure you parse the correct JSON object!
parse: function(response) {
return response.posts;
},
url: function() {
return '/api/core/get_category_posts/' + this.url_querystring;
},
model: Posts.Models.CategoryPost
});