emberJS does not display model data - javascript

I am using emberJS to display data obtained from REST API. My ember app connects to REST server and server returns the JSON data, but when I try to display id of my restaurant in the template I get this output:
Restaurant id is:
Here are my models:
import DS from 'ember-data';
//restaurant.js model
export default DS.Model.extend({
restaurantId: DS.attr('int'),
name: DS.attr('string'),
rating: DS.attr('double'),
phone: DS.attr('double'),
reservationPrice: DS.attr('double'),
workingHours: DS.attr('string'),
deals: DS.attr('string'),
image: DS.attr('string'),
//Relations
coordinates: DS.belongsTo('coordinates'),
address: DS.belongsTo('address')
});
//coordinates.js model
import DS from 'ember-data';
export default DS.Model.extend({
latitude: DS.attr("double"),
longitude: DS.attr("double"),
//Relations
restaurant: DS.belongsTo('restaurant')
});
//address.js model
import DS from 'ember-data';
export default DS.Model.extend({
streetName: DS.attr("string"),
city: DS.attr("string"),
country: DS.attr("string"),
//Relations
restaurant: DS.belongsTo('restaurant')
});
my template:
Restaurant id is: <br>
{{restaurant.restaurantId}}
<br>
{{model.restaurantId}}
{{#each model as |restaurant|}}
<h2>{{restaurant.image}}</h2>
{{/each}}
and my route:
//restaurant.js route
import Ember from 'ember';
export default Ember.Route.extend({
model() {
return this.store.findAll('restaurant');
}
});
and of course, my serializer:
import DS from 'ember-data';
export default DS.RESTSerializer.extend({
normalizeFindAllResponse(store, type, payload){
return {
id: "restaurantId",
data: {
type: type.modelName,
id: "restaurantId",
attributes: {
id: "restaurantId",
restaurantId: payload.restaurantId,
name: payload.name,
address: payload.address,
phone: payload.phone,
workingHours: payload.workingHours,
rating: payload.rating,
image: payload.image
}
}
};
}
});
Here is the JSON I get from server:
[ {
"restaurantId" : 1,
"name" : "Some name",
"address" : {
"streetName" : "some street",
"city" : "some town",
"country" : "some country"
},
"phone" : 984894,
"workingHours" : "08:00 - 23:00",
"rating" : 3.0,
"image" : "www.somelink.com"
},
...
]
I can see in Chrome inspector that my ember App makes a request to server and server responds with JSON. And there are no errors nor warnings, but my model data just does not get displayed. Any help is appreciated.
edit:
I wrote this normalizeFindRecord in my serializer, and now it looks like this:
normalizeFindRecordResponse(store, type, payload){
return {
data: {
type: type.modelName,
id: "restaurantId",
address: DS.belongsTo('restaurant', {embedded: true} ),
attributes: {
restaurantId: payload.restaurantId,
name: payload.name,
address: payload.address,
phone: payload.phone,
workingHours: payload.workingHours,
rating: payload.rating,
image: payload.image,
coordinates: payload.coordinates
}
}
};
}
and now when I try route this.store.findRecord('restaurant', 1); I get
Restaurant id is:
1
but the findAllRoute does still not work.

Related

Ember Data Polymorphic Relationship: Not Using Correct Model

Using an older version of ember(1.7.1) and ember-data(1.0.0 beta 12) as trying to upgrade to 2.0. When loading my application I get the following warning:
WARNING: The payload for 'App.QPAC' contains these unknown keys: [abs_parent_gbid,author,comments,course,follows,has_more_comments,is_announcement,more_comments_count,resource_uri,title]. Make sure they've been defined in your model.
Here is my model code (There are other models than post but they aren't being loaded in this instance).
App.Feedstory = DS.Model.extend({
global_id: DS.attr('string'),
story_type: DS.attr('string'),
story: DS.belongsTo('qPAC', {polymorphic: true}),
});
App.QPAC = DS.Model.extend({
global_id: DS.attr('string'),
global_code: DS.attr('string'),
body: DS.attr('string'),
});
App.Post = App.QPAC.extend({
title: DS.attr('string'),
is_announcement: DS.attr('boolean'),
author: DS.belongsTo('user'),
comments: DS.hasMany('comment'),
});
Ember inspector is showing me that the all the feedstory objects of type Post are being found and it shows in the Post attributes that the correct IDs are being loaded but not the other attributes.
The warning says it's looking for the post attributes in the App.QPAC model and not App.Post. Any ideas?
Edit: Added serializers and adapters
App.ApplicationAdapter = DS.RESTAdapter.extend({
namespace: 'api/v2'
});
App.FeedstorySerializer = DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
primaryKey: 'global_id',
attrs: {
pin: {embedded: 'always' },
story: {embedded: 'always'},
},
});
App.PostSerializer = DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
primaryKey: 'global_id',
attrs: {
author: {embedded: 'always' },
course: {embedded: 'always' },
pin: {embedded: 'always' },
comments: {embedded: 'always'},
follows: {embedded: 'always'},
},
normalize: function(type, hash, prop) {
if (Object.keys(hash.comments).length === 0) {
hash.comments = null;
}
if (Object.keys(hash.follows).length === 0) {
hash.follows = null;
}
return this._super(type, hash, prop);
},
});

codeschool emberjs 7.4 rating a product not working

I have been battling the level 7.4 review question with no luck:
Rating isn’t a object like Review was, so our createRating function will be a little different. We can addObject the currently selected rating to the array of ratings on our product. You’ll need to save the product to update it in the store.
I can not seem to get the value from the select list. Can anyone point me in the right direction or collaborate on this?
My handlebars code:
<script type='text/x-handlebars' data-template-name='product'>
<div class='row'>
<div class='col-sm-7'>
<h2>{{title}}</h2>
<h3 class='text-success'>${{price}}</h3>
<p class='text-muted'>{{description}}</p>
<p class='text-muted'>This Product has a {{rating}} star rating!</p>
<p>Finely crafted by {{#link-to 'contact' crafter}}{{crafter.name}}{{/link-to}}.</p>
{{render 'reviews' reviews}}
<div class='new-rating'>
<h3>Rate {{title}}</h3>
</div>
<div class='new-review'>
<h3>Review {{title}}</h3>
{{#if text}}
<p class='text-muted'>{{text}}</p>
{{/if}}
{{textarea valueBinding='text'}}
<button {{action 'createReview'}} class='btn-primary'>Review</button>
</div>
</div>
<div class='col-sm-5'>
<img {{bind-attr src='image'}} class='img-thumbnail img-rounded'/>
</div>
</div>
{{contact-details contact=crafter className='row'}}
{{view Ember.Select content=ratings value=selectedRating}}
<button {{action 'createRating'}} class='btn-primary'>Rating</button>
</script>
My js code:
var App = Ember.Application.create({
LOG_TRANSITIONS: true
});
App.Router.map(function() {
this.route('credits', { path: '/thanks' });
this.resource('products', function() {
this.resource('product', { path: '/:product_id' });
this.route('onsale');
this.route('deals');
});
this.resource('contacts', function() {
this.resource('contact', { path: '/:contact_id' });
});
});
App.IndexController = Ember.ArrayController.extend({
productsCount: Ember.computed.alias('length'),
logo: 'images/logo-small.png',
time: function() {
return (new Date()).toDateString();
}.property(),
onSale: function() {
return this.filterBy('isOnSale').slice(0,3);
}.property('#each.isOnSale')
});
App.ContactsIndexController = Ember.Controller.extend({
contactName: 'Anostagia',
avatar: 'images/avatar.png',
open: function() {
return ((new Date()).getDay() === 0) ? "Closed" : "Open";
}.property()
});
App.ProductsController = Ember.ArrayController.extend({
sortProperties: ['title']
});
App.ContactsController = Ember.ArrayController.extend({
sortProperties: ['name'],
contactsCount: Ember.computed.alias('length')
});
App.ReviewsController = Ember.ArrayController.extend({
sortProperties: ['reviewedAt'],
sortAscending: false
});
App.ContactProductsController = Ember.ArrayController.extend({
sortProperties: ['title']
});
App.ProductController = Ember.ObjectController.extend({
text: '',
ratings: [1,2,3,4,5],
selectedRating: 5,
actions: {
createReview: function(){
var review = this.store.createRecord('review', {
text: this.get('text'),
product: this.get('model'),
reviewedAt: new Date()
});
var controller = this;
review.save().then(function() {
controller.set('text', '');
controller.get('model.reviews').addObject(review);
});
},
createRating: function(){
var rating = this.store.createRecord('rating', {
rating: this.get('selectedRating.value'),
product: this.get('model'),
reviewedAt: new Date()
});
var controller = this;
rating.save().then(function() {
controller.get('model.rating').addObject(rating);
});
}
}
});
App.ProductsRoute = Ember.Route.extend({
model: function() {
return this.store.findAll('product');
}
});
App.ContactsRoute = Ember.Route.extend({
model: function() {
return this.store.findAll('contact');
}
});
App.IndexRoute = Ember.Route.extend({
model: function(){
return this.store.findAll('product');
}
});
App.ProductsIndexRoute = Ember.Route.extend({
model: function(){
return this.store.findAll('product');
}
});
App.ProductsOnsaleRoute = Ember.Route.extend({
model: function(){
return this.modelFor('products').filterBy('isOnSale');
}
});
App.ProductsDealsRoute = Ember.Route.extend({
model: function(){
return this.modelFor('products').filter(function(product){
return product.get('price') < 500;
});
}
});
App.ProductDetailsComponent = Ember.Component.extend({
reviewsCount: Ember.computed.alias('product.reviews.length'),
hasReviews: function(){
return this.get('reviewsCount') > 0;
}.property('reviewsCount')
});
App.ContactDetailsComponent = Ember.Component.extend({
productsCount: Ember.computed.alias('contact.products.length'),
isProductive: function() {
return this.get('productsCount') > 3;
}.property('productsCount')
});
App.ProductView = Ember.View.extend({
isOnSale: Ember.computed.alias('controller.isOnSale'),
classNameBindings: ['isOnSale']
});
App.ApplicationAdapter = DS.FixtureAdapter.extend();
App.Product = DS.Model.extend({
title: DS.attr('string'),
price: DS.attr('number'),
description: DS.attr('string'),
isOnSale: DS.attr('boolean'),
image: DS.attr('string'),
reviews: DS.hasMany('review', { async: true }),
crafter: DS.belongsTo('contact', { async: true }),
ratings: DS.attr(),
rating: function(){
return this.get('ratings').reduce(function(previousValue, rating) {
return previousValue + rating;
}, 0) / this.get('ratings').length;
}.property('ratings.#each')
});
App.Product.FIXTURES = [
{ id: 1,
title: 'Flint',
price: 99,
description: 'Flint is a hard, sedimentary cryptocrystalline form of the mineral quartz, categorized as a variety of chert.',
isOnSale: true,
image: 'images/products/flint.png',
reviews: [100,101],
crafter: 200,
ratings: [2,1,3,3]
},
{
id: 2,
title: 'Kindling',
price: 249,
description: 'Easily combustible small sticks or twigs used for starting a fire.',
isOnSale: false,
image: 'images/products/kindling.png',
reviews: [],
crafter: 201,
ratings: [2,1,3,3]
},
{
id: 3,
title: 'Matches',
price: 499,
description: 'One end is coated with a material that can be ignited by frictional heat generated by striking the match against a suitable surface.',
isOnSale: true,
reviews: [],
image: 'images/products/matches.png',
crafter: 201,
ratings: [2,1,3,3]
},
{
id: 4,
title: 'Bow Drill',
price: 999,
description: 'The bow drill is an ancient tool. While it was usually used to make fire, it was also used for primitive woodworking and dentistry.',
isOnSale: false,
reviews: [],
image: 'images/products/bow-drill.png',
crafter: 200,
ratings: [1,3,3]
},
{
id: 5,
title: 'Tinder',
price: 499,
description: 'Tinder is easily combustible material used to ignite fires by rudimentary methods.',
isOnSale: true,
reviews: [],
image: 'images/products/tinder.png',
crafter: 201,
ratings: [2,1,3]
},
{
id: 6,
title: 'Birch Bark Shaving',
price: 999,
description: 'Fresh and easily combustable',
isOnSale: true,
reviews: [],
image: 'images/products/birch.png',
crafter: 201,
ratings: [2,3,5]
}
];
App.Contact = DS.Model.extend({
name: DS.attr('string'),
about: DS.attr('string'),
avatar: DS.attr('string'),
products: DS.hasMany('product', { async: true })
});
App.Contact.FIXTURES = [
{
id: 200,
name: 'Giamia',
about: 'Although Giamia came from a humble spark of lightning, he quickly grew to be a great craftsman, providing all the warming instruments needed by those close to him.',
avatar: 'images/contacts/giamia.png',
products: [1,4]
},
{
id: 201,
name: 'Anostagia',
about: 'Knowing there was a need for it, Anostagia drew on her experience and spearheaded the Flint & Flame storefront. In addition to coding the site, she also creates a few products available in the store.',
avatar: 'images/contacts/anostagia.png',
products: [2,3,5,6]
}
];
App.Review = DS.Model.extend({
text: DS.attr('string'),
reviewedAt: DS.attr('date'),
product: DS.belongsTo('product')
});
App.Review.FIXTURES = [
{
id: 100,
text: "Started a fire in no time!"
},
{
id: 101,
text: "Not the brightest flame, but warm!"
}
];
After detailed research, the answer turned out being:
createRating: function() {
var prod = this.get('model');
var ratings = this.get('model.ratings');
ratings.addObject(this.selectedRating);
prod.save();
}
In the code shown, you should be getting the rating using this.get('selectedRating') not this.get('selectedRating.value')
http://emberjs.jsbin.com/xohidixe/1/edit

serialize underscored property ember-data

My serialzer works fine, exept for underscored properties. The sctucture of the JSON from server is:
var services = {
services:[{
id:8,
name:"Codin'",
service_category:{
id:5,
iso_code:"BDT",
prop:"Ohmmmm"
}
},
{
id:7,
name:"PR",
service_category:{
id:2,
iso_code:"SFD",
prop:"Naraya"
}
}]
};
after serialisation the payload looks like this:
var services = {
services:[{
id:8,
name:"Codin'",
service_category:5
},
{
id:7,
name:"PR",
service_category:2
}],
serviceCategories:[{
id:5,
iso_code:"BDT",
prop:"Ohmmmm"
},
{
id:2,
iso_code:"SFD",
prop:"Naraya"
}
]
};
But it in the template i cant access serviceCategory's prop
The models
App.Service = DS.Model.extend({
name: DS.attr('string'),
serviceCategory: DS.belongsTo('serviceCategory')
});
App.ServiceCategory = DS.Model.extend({
iso_code: DS.attr('string'),
prop:DS.attr()
});
Here is the JsBin as usual: http://jsbin.com/OxIDiVU/565
Your json has service_category as the property name in the service.
Easy fix is:
App.Service = DS.Model.extend({
name: DS.attr('string'),
service_category: DS.belongsTo('serviceCategory')
});
and
<td>{{item.service_category.prop}} </td>
http://jsbin.com/OxIDiVU/570/edit

How to display nested data in template from Ember.js model using basic adapter?

Store:
App.Store = DS.Store.extend({
revision: 12,
adapter: DS.BasicAdapter.create()
});
Model:
var Profiles = DS.Model.extend({
displayName: DS.attr('string'),
profileName: DS.attr('string')
}),
User = DS.Model.extend({
email: DS.attr('string'),
phone: DS.attr('string'),
profiles: DS.hasMany(Profiles, {embedded: true})
});
JSON data for model:
{
"email": "some email",
"phone": "some phone number",
"profiles": [
{
"displayName": "some name",
"profileName": "some name"
},
{
"displayName": "some name",
"profileName": "some name"
}
]
}
In the template:
{{#if model.isLoaded}}
email: {{model.email}} // displayed
{{model.profiles.length}} // number of objects in array is displayed
{{#each model.profiles}}
// this line generates error Uncaught TypeError: Cannot call method
'_create' of undefined ember-data.js:2560
{{/each}}
{{/if}}
Any idea why this line generates an error? Especially if model.profiles.length displays correct value?
At first, the syntax you used for embedding Profiles in user is not relevant anymore. Please check this answer for a proper way to set this.

Ember Data - Assign a value inside an object

I'm starting up with ember and trying to get some data from an Api and assign it to an Emberjs model.
My api returns something like:
[
{
email: 'someemail#domain.com'
name: {
firstname: 'first name',
lastname: 'last name'
}
}
{
email: 'someemail2#domain.com'
name: {
firstname: 'another first name',
lastname: 'another last name'
}
},
{
email: 'someemail3#domain.com'
name: undefined
}
]
And my code is:
App.Store = DS.Store.extend({
revision: 12,
});
App.Store.registerAdapter('App.Users', DS.Adapter.extend({
findAll: function(store, type, id) {
$.getJSON('https://domain.com/users?callback=?', {
'auth_token': token
}).done(function(json){
store.loadMany(type, json);
});
},
}));
App.Store.registerAdapter('App.Users', DS.Adapter.extend({
findAll: function(store, type, id) {
$.getJSON('https://domain.com/users?callback=?', {
'auth_token': token
}).done(function(json){
store.loadMany(type, json);
});
},
}));
App.Router.map(function() {
this.route("users", { path: "/users" });
});
App.UsersRoute = Ember.Route.extend({
model: function() {
return App.Users.find();
}
});
App.Users = DS.Model.extend({
email: DS.attr('string'),
firstname: DS.attr('string'),
didLoad: function() {
console.log('model loaded', this.toJSON());
}
});
<script type="text/x-handlebars" data-template-name="users">
{{#each model}}
{{email}} - {{firstname}}
{{/each}}
</script>
Obviously firstname is empty for every object in the array.
Does anyone know what's the proper way to do this?
Thanks
Have you tried setting up your User model like this:
App.Adapter.map('App.User', {
name: {embedded: 'always'}
});
App.User = DS.Model.extend({
email: DS.attr('string'),
name: DS.belongsTo('App.UserName')
});
App.UserName = DS.Model.extend({
firstName: DS.attr('string'),
lastName: DS.attr('string')
});

Categories