Ember.js make model of embedded / sideloaded data - ember.js

To use ember validations I need to make a model of embedded data. I use Ember CLI.
The JSON looks something like this:
{
"endpoint": {
"name": "Name of form",
"form_settings": {
"id": 2,
"setting_one": "Setting 1"
},
"id": 2
}
}
I've made this serializer:
import applicationSerializer from 'closealert-ui/serializers/application';
import DS from 'ember-data';
var endpointSerializer = applicationSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
endpointFormSettings: {embedded: 'always'}
}
});
export default endpointSerializer;
I've made an endpoint model:
import DS from 'ember-data';
export default DS.Model.extend({
formName: DS.attr('string'),
formSettings: DS.belongsTo('endpointFormSettings'),
});
And I've made an enpoint-form-settings model:
import DS from 'ember-data';
export default DS.Model.extend({
endpoint: DS.belongsTo('endpoint'),
settingOne: DS.attr('string')
});
When I look in the ember inspector the endpointFormSettings model is still empty. What am I missing?

Related

Accessing Nested JSON in Ember Model

I'm trying to access a particular ID which is nested inside my model to make a belongsTo association. I have no trouble getting what I need in my template, but need image_id within my model. Below is my JSON and current model.
{
content: {
title: 'Title',
header: 'Header',
image_id: 1
}
slug: 'slug',
title: 'Welcome'
}
Here is my current model...
import DS from 'ember-data';
const { attr } = DS;
export default DS.Model.extend({
content: attr(),
title: attr('string'),
});
Hope this makes sense!! Thanks!
I have similar use-cases (mostly a very variable settings paramter that is stored as json in db) and solved it via a custom transform:
// myapp/transforms/json.js
import DS from 'ember-data';
// Converts stringified json coming from database (usually in table-field 'settings') to a POJO
export default DS.Transform.extend({
deserialize: function(serialized) {
return JSON.parse(serialized);
},
serialize: function(deserialized) {
return JSON.stringify(deserialized);
}
});
//myapp/models/myModel.js
import DS from 'ember-data';
export default DS.Model.extend({
title: DS.attr('string'),
content: DS.attr('json')
});
Then in your template you should be able to do
{{model.content.image_id}}
Or in controller
let image_id = this.get('model.content.image_id');
or in model
this.get('content.image_id');

findAll throwing error

I am using a simple findAll query in my ember application ( ember-version: 2.12.0, ember-data-version: 2.12.1 ) and I get the following error:
Assertion Failed: You can no longer pass a modelClass as the first argument to store.buildInternalModel. Pass modelName instead.
I am using the RESTAdapter and RESTSerializer.
Here is my team model:
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
projects: DS.hasMany('project'),
users: DS.hasMany('user'),
members: Ember.computed('users', function() {
return this.get('users.content.length');
}),
leader: DS.belongsTo('user', {
inverse: 'team'
})
});
and my team serializer:
import ApplicationSerializer from './application';
import DS from 'ember-data';
export default ApplicationSerializer.extend(DS.EmbeddedRecordsMixin,{
attrs: {
users: { async: true },
projects: { async: true }
}
});
Despite the error, the team objects I requested are in the store. I had no luck in solving this so far.
Actually the problem was in the serializer and the payload from the server. I should have attrs: {users: {embedded: 'always'}} as users where in the payload from the server.

You need to pass a model name to the store's modelFor method

I have problem with making hasMany <=> belongTo relationship to work.
I have articles/show view, when I try to list article's comments but I keep recieving the error pointed in the title.
It's something with belongsTo: DS.belongsTo('article') but I couldn't figure out what it is.
Here are my files.
routes/articles/show.js
import Ember from 'ember';
import RSVP from 'rsvp';
export default Ember.Route.extend({
model(params) {
return RSVP.hash({
article: this.store.find("article", params.id),
comments: this.store.query('comment', { articleId: params.id })
});
}
});
controllers/articles/show.js
import Ember from 'ember';
const { computed: { alias, readOnly } } = Ember;
export default Ember.Controller.extend({
article: alias('model.article'),
comments: alias('model.comments'),
length: readOnly('comments.length')
});
templates/articles/show.hbs
<h3>Comments ({{comments.length}})</h3>
{{#each comments as |comment|}}
<p>Author: {{comment.user.name}}</p>
<p>Somebody said: {{comment.body}}</p>
{{/each}}
adapters/comment.js
import ApplicationAdapter from './application';
export default ApplicationAdapter.extend({});
serializers/comment.js
import DS from 'ember-data';
export default DS.RESTSerializer.extend({
attrs: {
user: { embedded: 'always' },
article: { embedded: 'always' }
}
});
serializers/article.js
import DS from 'ember-data';
export default DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
comments: { embedded: 'always' }
}
});
models/article.js
import DS from 'ember-data';
import Ember from 'ember';
const { attr, hasMany } = DS;
const { computed: { gt } } = Ember;
export default DS.Model.extend({
title: attr('string'),
content: attr('string'),
authorName: attr('string'),
authorAvatar: attr('string'),
authorUrl: attr('string'),
comments: hasMany('comment', {async: true}),
hasAvatar: gt('authorAvatar.length', 0)
});
Edit:
I added here the code for comment model as asked in the comments.
models/comment.js
import DS from 'ember-data';
const { belongsTo, attr } = DS;
export default DS.Model.extend({
article: belongsTo(),
user: belongsTo(),
body: attr('string')
});
And here is stacktrace from inspector:
ember.debug.js:16905 Assertion Failed: You need to pass a model name to the store's modelFor method
Error
at assert (http://ffl.com:8000/assets/vendor.js:16268:13)
at Object.assert (http://ffl.com:8000/assets/vendor.js:27196:34)
at assert (http://ffl.com:8000/assets/vendor.js:135212:37)
at Class.modelFor (http://ffl.com:8000/assets/vendor.js:145201:41)
at Class._internalModelForId (http://ffl.com:8000/assets/vendor.js:144337:29)
at Class._pushResourceIdentifier (http://ffl.com:8000/assets/vendor.js:145716:19)
at BelongsToRelationship.updateData (http://ffl.com:8000/assets/vendor.js:142394:36)
at BelongsToRelationship.push (http://ffl.com:8000/assets/vendor.js:142976:14)
at http://ffl.com:8000/assets/vendor.js:145795:20
at http://ffl.com:8000/assets/vendor.js:141943:18
defaultDispatch # ember.debug.js:16905
dispatchError # ember.debug.js:16888
onerrorDefault # ember.debug.js:30389
trigger # ember.debug.js:57833
(anonymous) # ember.debug.js:58717
invoke # ember.debug.js:339
flush # ember.debug.js:407
flush # ember.debug.js:531
end # ember.debug.js:601
run # ember.debug.js:724
join # ember.debug.js:746
run.join # ember.debug.js:21556
hash.success # rest.js:954
fire # jquery.js:3305
fireWith # jquery.js:3435
done # jquery.js:9242
(anonymous) # jquery.js:9484
I checked your issue and repo. The problem was just with comment serializer in Ember.js. It should be:
import DS from 'ember-data';
export default DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
article: { embedded: 'always' },
user: { embedded: 'always' }
}
});
I cloned your project branch refactor-and-upgrade-ember but mirage is not done. So I looked at the code
headTags() {
let article = this.modelFor(this.routeName);
}
This is in routes articles show ,can you try and remove it and try.

Assertion Failed: You must include an 'id' for account in an object passed to 'push' Ember.js v-2.4

I'm new to Ember and I can't find anywhere a solution to my problem. I have read the questions here in stack and in other ember forums, but none of them seems to work for me.
I'm trying to create a simple signup form. I should note that for the backend I use django.
Here is my code:
Server Response:
[{"username":"user1","password":"123","email":"user1#example.com"},
{"username":"user2","password":"456","email":"user2#example.com"}]
Ember Model:
import DS from 'ember-data';
export default DS.Model.extend({
username: DS.attr(),
password: DS.attr(),
email: DS.attr()
});
Ember Adapter:
import DS from 'ember-data';
export default DS.RESTAdapter.extend({
host: '/api',
contentType: 'application/json',
dataType: 'json',
headers: {
username: 'XXXX',
password: 'XXXX'
}
});
Ember Serializer:
import DS from 'ember-data';
export default DS.JSONSerializer.extend({
primaryKey: '_id'
});
Ember Route:
import Ember from 'ember';
export default Ember.Route.extend({
model() {
return this.store.findAll('account');
}
});
Ember Controller:
import Ember from 'ember';
export default Ember.Controller.extend({
actions: {
signup(){
console.log('My username is: ', this.get('username'));
console.log('My password is: ', this.get('password'));
console.log('My email is: ', this.get('email'));
var account = this.store.createRecord('account', {
username: this.get('username'),
password: this.get('password'),
email: this.get('email')
});
account.save();
}
}
});
With this implementation I get the aforementioned error. Any help would be appreciated. Thank you in advance.
Your backend should respond with an id, i.e
{"id":123,"username":"user1","password":"123","email":"user1#example.com"}
You don't really need to use the serializer, unless you want a specific field to act as an id. So in the example above, ember-data would expect your backend to return
{**"_id":123**,"username":"user1","password":"123","email":"user1#example.com"}
Or you could do something like this:
import DS from 'ember-data';
export default DS.JSONSerializer.extend({
primaryKey: 'username'
});
And use your username as an id.
I fixed my error. The problem was that the backend was using username as id so ember could not recognized it.
The fixed code for the Ember Serializer is:
import DS from 'ember-data';
export default DS.JSONSerializer.extend({
primaryKey: 'username'
});

Ember data JSON Api adapter set all attributes to undefined

In an application using ember 2.1.0 and ember-data 2.1.0, I have this model :
# app/models/user.js
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr()
});
And this route :
# app/routes/subscriptions/new.js
export default Ember.Route.extend({
model() {
this.store.findRecord('user', 1).then(function(data) {
console.log(data.id)
console.log(data.get('email'))
})
return this.store.find('user', 1);
}
});
I have this adapter :
import DS from 'ember-data';
export default DS.JSONAPIAdapter.extend({host: 'http://localhost:5000'})
This data is returned by the server :
{"data":{"id":"1","type":"users","attributes":{"email":"test#test.com"}}}
In the console, I have the user id but the email is undefined. In the template, {{model.email}} gives nothing.
I may miss something but it's so simple. Is it my mistake or a bug?
You have to also specify email attribute in model:
export default DS.Model.extend({
name: DS.attr('string'),
email: DS.attr('string')
});