How to access complex nested json in ember.js - ember.js

after thorough searching stackoverflow and reading through all of the documetation on emberjs.com I'm finding myself stuck. I have a complex json object that I'm trying to model and output in my ember project.
I don't have control over the JSON, otherwise I'd change it's format to be easier digested. That said, here is my problem.
I have the following json
[
{
"id":1,
"catId": "10051",
"catUrl": "path/to/location",
"childCount": "4",
"description": [{
"text": "Description Text"
}],
"identifier": "UNQ123456",
"partialResults": "false"
}
]
What I'm trying to get at is the text value in description. I've tried creating the hasMany and belongsTo nested model construct described on emberjs.com, as well as many other patterns that were described as answers here on stack overflow, yet none of them seem to work or match the data construct I have to work with.
I've even tried the anonymous function in the first block of code on this page. http://emberjs.com/guides/models/defining-models/ trying to traverse this to the text that I want.
Regardless, any help would be much appreciated.

You could define a custom data transform to handle your special JSON field. This can be done by using the DS.RESTAdapter.registerTransform function. Something like this should work for your use case:
DS.RESTAdapter.registerTransform('descriptionText', {
serialize: function(data) {
var text = data[0].text;
return text;
},
deserialize: function(text) {
var data = [Ember.create({text: text})];
return data;
}
});
And then use it as a custom attribute for your model:
App.MyModel = DS.Model.extend({
...
description: DS.attr('descriptionText')
});
Note that the name of the transform could be something else as descriptionText as long you use the same name for DS.attr(...).
Hope it helps.

Related

Ember-models-table addon throws ember warn error while trying to use 'routeName' property

Am using ember-models-table to display table in my applicaiton. The table is great for sorting , pagination etc, but am trying to route from specific row to different page based on the id. it has mentioned in its example to use 'routeName'
But when I use it throws the following error:
"Assertion Failed: When calling warn you must provide an options hash as the third parameter. options should include an id property."
My .js coding :
columns:[
{
"propertyName": "firstName",
"title":"First Name",
"routeName":"/#/profile/_id"
},
and so on
Thanks for your help.
update: the error is gone after updating ember to ember 3.1.2
but there is a warning and its not functioning properly as expected , where am i going wrong?
my code :
columns:[
{
"propertyName": "firstName",
"title":"First Name",
"routeName":"profile"
},
If you look at the example app for this addon, you'll see the following syntax for the route:
{
propertyName: 'id',
routeName: 'users.user'
},
This roughly corresponds to a route like users/1. So, if this is your router:
Router.map(function() {
this.route('users', function() {
this.route('user', { path: '/users/:user_id' });
});
});
And here are the columns:
columns: [
{
"propertyName": "something",
"routeName": "users.user"
},
{
"propertyName": "id",
"routeName": "users.user"
}
]
Here's the template:
{{models-table
data=model
columns=columns
...
}}
routeName should not include the id segment.
Hover over the anchor tag created to see where it leads to, and make adjustments until it matches where it should go. It will only render when there's a valid route for the link. The path seems like it might be relative, so if you're already on the users route, you may only need to specify user for the routeName.
I figured this out by searching the addon codebase for routeName and then trying it out with the same kind of format that {{link-to}} helper uses in Ember.
P.S. this is some missing info in the documentation, so if this addon is helping you out, consider making a PR to help others.

Define graphQLSchema properly in Node.js

Doing graphQL first time.I searched for resources but could not found a helpful one.
I have written the following schema, got some help from another stackoverflow post.
schema.js
function getDataFromUrl(){
return [
{
"EventCode": "ET00029280",
"EventType": "CT",
"EventTitle": "OYSTERS Beach Park",
"VenueName": "Newexcelsior",
"VenueRegion": "Mumbai"
},
{
"EventCode": "ET00030629",
"EventType": "CT",
"EventTitle": "Stand-Up Comedy: The Trial Room",
"VenueName": "Newexcelsior",
"VenueRegion": "Mumbai"
}
];
}
const eventType = new GraphQLObjectType({
name: 'Event',
fields: {
EventTitle: {
type: GraphQLString,
description: 'Event Title'
},
},
});
const eventListType = new GraphQLObjectType({
name: 'EventList',
fields: {
events: {
type: new GraphQLList(eventType),
description: 'List of items',
},
},
});
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: {
eventList: {
type: new GraphQLList(eventListType),
resolve: () => getDataFromUrl(),
}
}
})
});
module.exports = schema;
When I query
{
eventList {
events {
EventTitle
}
}
}
I get this response:
{
"data": {
"eventList": [
{
"events": null
},
{
"events": null
}
]
}
}
I am expecting some changes in my schema, however my desired response is
{
"data": [
{
"EventTitle": "OYSTERS Beach Park"
},
{
"EventTitle": "Stand-Up Comedy: The Trial Room"
}
]
}
Please also suggest some links where I learn basics.
It looks like what's tripping you up the most right now is how you're defining a list. There's no need to define a separate type called EventList -- when you specify GraphQLList(someOtherType) you are already telling GraphQL to expect an array of that particular type. Your current Schema is expecting an array of an array of types. Because the structure of the data you're passing in doesn't match your schema, GraphQL can't find a field called EventTitle to match against and so it's returning null.
The fix in this case is to just get rid of eventListType altogether and change the type of your eventList field to eventType instead.
The docs for GraphQL.js are probably going to be your best bet as far as learning the basics. The only problem is the examples they include are way too basic. Here is a list of projects on GitHub that you can checkout to see GraphQL in action.
If you are starting out, I would also highly recommend using Apollo's graphql-tools. Even if you don't use Apollo on the client-side, graphql-tools makes it ridiculously easy to set up the server. Your schema would be much more readable, since you would write it as string rather than an object like you do in vanilla GraphQL.js. And you can easily set up a GraphiQL endpoint in addition to your GraphQL one, which makes debugging much easier :)

Loading a single record with Ember 2.0 and Ember Data 2.0

I've come unstuck when trying to fetch a single record using Ember Data 2.
The server is designed to respond to a GET request like this:
GET http://server/api/results/1
with this as a result:
{
"results" : [
{
"id": 1,
"catname": "Category 1",
}
]
}
The Ember route code looks like this:
export default Ember.Route.extend({
model: function() {
return this.store.find('game',12);
}
});
The problem is that there doesn't appear to be a network request going out (a previous findAll fetch has worked, so I don't think it's the adapter), and there is an error I have not been able to find informaiton on:
Uncaught TypeError: Cannot set property'crossDomain' of undefined
Does anyone have any idea what this could be, of hint at how I might track this down?
In 1.13 new methods was introduced. You should use findRecord instead of find.
Also, ember expects following response when fetching a single object:
{
"result" :
{
"id": 1,
"catname": "Category 1",
}
}

ObjectAt(0) doesn't work with Ember.Controller

I'm trying to upgrade my Ember application to the latest Ember 1.13.2 and therefore am trying to replace all Ember.ArrayController with Ember.Controller.
I've got a problem with the category-controller of my blog. The data retrieved from my server looks like this:
"posts": [
{
"category": {
"id": "1",
"name": "tech"}
"title": "my title",
"body": "post-content",
"isPublished": true,
},
...
]
In my category-controller I need both, the category-id and the category-name.
With the Ember.ArrayController I used objectAt(0) to get both from the first post loaded in the model for that purpose but this doesn't work with Ember.Controller anymore.
How can I get these two attributes in my controller?
This code doesn't work anymore:
breadCrumb: function(){
return this.objectAt(0).get('category').get('name');
}.property('model.[]'),
categoryId: function(){
return this.objectAt(0).get('category').get('id');
}.property('model.[]'),
You just get it from the model directly instead of using the proxy behavior:
return this.get('model').objectAt(0).get('category').get('name');
Or, if you like shorthand:
return this.get('model.firstObject.category.name');
EDIT: While I'm at it, you could also declare these as aliases:
breadCrumb: Ember.computed.alias('model.firstObject.category.name'),
If you don't do that, you should probably change your dependent key. Your property won't update if the nested properties change. You need to use something like model.firstObject.category.name or model.#each.category.name.

How to Model.fetch(<object>) when the returned data is a single object

I want to make an API call for searching that looks like this:
https://myapi.com/search/<query>/<token>
where query is the search term and token (optional) is an alphanumeric set of characters which identifies the position of my latest batch of results, which is used for infinite scrolling.
This call returns the following JSON response:
{
"meta": { ... },
"results" {
"token": "125fwegg3t32",
"content": [
{
"id": "125125122778",
"text": "Lorem ipsum...",
...
},
{
"id": "125125122778",
"text": "Dolor sit amet...",
...
},
...
]
}
}
content is an array of (embedded) items that I'm displaying as search results. My models look like this:
App.Content = Em.Model.extend({
id: Em.attr(),
text: Em.attr(),
...
});
App.Results = Em.Model.extend({
token: Em.attr(),
content: Em.hasMany('App.Content', {
key: 'content',
embedded: true
})
});
In order to make that API call, I figured I have to do something like this:
App.Results.reopenClass({
adapter: Em.RESTAdapter.create({
findQuery: function(klass, records, params) {
var self = this,
url = this.buildURL(klass) + '/' + params.query;
if (params.token) {
url += '/' + params.token;
}
return this.ajax(url).then(function(data) {
self.didFindQuery(klass, records, params, data);
return records;
});
}
}),
url: 'https://myapi.com/search',
});
then somewhere in my routes do this:
App.Results.fetch({query: 'query', token: '12kgkj398512j'}).then(function(data) {
// do something
return data;
})
but because the API returns a single object and Em.RESTAdapter.findQuery expects an array, an error occurs when Ember Model tries to materialize the data. So how do I do this properly? I'm using the latest build of Ember Model.
By the way, I'm aware that it would be much more convenient if the API was designed in a way so I can just call App.Content.fetch(<object>), which would return a similar JSON response, but I would then be able to set the collectionKey option to content and my data would be properly materialized.
You simply need to override your models load() method to adjust the payload hash to what Ember.Model wants. There are no serializers in Ember.Model. There is both a class level load for handling collections and an instance level load for loading the JSON specific to a single model. You want to override the instance level load method to wrap the content key value in an array if its not one already.
I have been using Ember.Mode quite heavily and enhanced it for a number of my use cases and submitted PR's for both fixes and enhancements. Those PRs have been sitting there for a while with no response from the maintainers. I have now moved to Ember.Data which has been 'rebooted' so to speak and having a lot better result with it now.
I would strongly suggest walking away from Ember.Model as it appears dead with the new pragmatic direction Ember Data has taken and because the project maintainer doesn't appear to have any interest in it anymore.