I can't seem to workout how to load relationships properly in Ember. The user model only returns some of the time. If I refresh the page there seems to be a 50/50 chance the value will be null, or it will resolve correctly.
I understand in the route I'm returning a promise which is the server object (the belongsTo end of the user relationship), but how do I tell the route to wait for the user model to load before loading the page, or how do I tell ember to update the data on the page when it finally does load the user?
I've tried playing around with RSVP in the afterModel hook but haven't had any luck. There must be a obvious solution to this?
route
model(param) {
return this.store.findRecord('server', param.server_id);
},
server model
export default Model.extend(Validations, {
user: belongsTo('user'),
});
user model
export default Model.extend({
displayName: attr('string'),
servers: hasMany('server'),
});
component
export default Ember.Component.extend({});
component template
<div class="user-panel">
<ul class="user-details">
<li>owner:{{model.user.displayName}}</li>
</ul>
</div>
I've read a similar question here How to load belongsTo/hasMany relationships in route with EmberJS
But as I'm only returning a single object rather than an array I get Array Methods must be provided an Array thrown when trying any of the solutions
Server response
{
"data": {
"type": "server",
"id": "578aba694b08ce2310f36798",
"attributes": {
//removed
},
"relationships": {
"jobs": {
"data": [
{
"type": "jobs",
"id": "578aba694b08ce2310f3679a"
}
]
},
"user": {
"data": {
"type": "user",
"id": "57760677d04e0f11f4d3f7e5"
}
}
}
}
}
This should work out of the box! Not the waiting part, but the auto update.
Checkout this twiddle.
But if you want to wait for the model you can just enforce this in the afterModel hook:
afterModel(model) {
return get(model, 'user');
}
Related
I'm using RESTAdapter and trying to figure out how to access sideloaded data.
A sample of the payload is:
{
"category": {
"categoryName": "test category",
"id": 6,
"products": [
4419,
502,
3992
]
},
"products": [{
"description": "Whatevs",
"id": 4419,
"name": "Product 1",
"price": 114.95,
"skuid": "S21046"
}, {
"description": "Whatevs",
"id": 502,
"name": "Product 2",
"price": 114.95,
"skuid": "SOLS2594"
}, {
"description": "Whatevs",
"id": 3992,
"name": "Product 3",
"price": 114.95,
"skuid": "S21015"
}]
}
I can see 'category' and 'product' data models (and data) in the ember inspector, so I know they are being loaded.
I can even access the products in the template model.products. BUT I can't access model.products in the route's setupController. The error I get is:
TypeError: Cannot read property '_relationships' of undefined
This is really perplexing me! My route model hook is:
model(params) {
return this.get('store').queryRecord('category', {
id: params.id
})
}
The setupController hook (that causes the error) is:
setupController(controller, model) {
controller.set('results', model.products);
}
The 'category' model:
export default DS.Model.extend({
products: hasMany('product'),
categoryName: attr('string')
});
The 'product' model:
export default DS.Model.extend({
name: attr('string'),
skuid: attr('string'),
price: attr('number'),
description: attr('string')
});
My template (which works, if I remove the 'setupController' hook from the route):
{{#each model.products as |product|}}
{{product.name}} {{product.skuid}}<br />
{{/each}}
I'd like to be able to access model.products from the route's setupController so I can call it something else. Any help appreciated.
Relationship returns Promises. so to get the result you need to use then. but accessing it in template will work because template is by default promise aware.
setupController(controller, model) {
//controller.set('results', model.products);
model.get('products').then((result) => {
controller.set('results',result);
});
}
Please give read on relationships as promises guide.
I'm still learning ember.js and have run into a roadblock with ember data not resolving lookup relationships in models. I have one model 'site' that will be basically a lookup table for every other model to differentiate data based on location.
At this point, I'm doing something wrong or missing a key concept - probably both... (or maybe it's the wee hour!)
Site Model (i.e. the lookup table)
import DS from 'ember-data';
export default DS.Model.extend({
code: DS.attr(),
name: DS.attr(),
});
The site model would have a hasMany relationship to all my other models (will be about 12 when complete)
Associate Model
import DS from 'ember-data';
import { belongsTo } from 'ember-data/relationships';
export default DS.Model.extend({
site: belongsTo('site'),
last: DS.attr(),
first: DS.attr(),
active: DS.attr('boolean'),
fullName: Ember.computed('first', 'last', function() {
return `${this.get('first')} ${this.get('last')}`;
}),
});
The 'associate model' will also be a lookup along with 'site' in some other models.
I'm providing data via the JSON API spec but I'm not including the relationship data because as I understand it, ember data it should be pulling down the site data using the site id attribute.
{
"links": {
"self": "/maint/associates"
},
"data": [
{
"type": "associate",
"id": "1",
"attributes": {
"site": "6",
"last": "Yoder",
"first": "Steven",
"active": "1"
},
"links": {
"self": "/associates/1"
}
}
]
}
In my template file I'm referencing associate.site which gives me an error.
<(unknown mixin):ember431>
If I use associate.code or .name to match the site model, nothing will show in the template. The code from the 'site' table is the data I really want to displayed in the template.
So the obvious questions:
Am I wrong that Ember Data should be resolving this or do I need to
include the relationship in my API response?
I realize that my belongsTo in the 'associate' model only references
site while I want site.code, so how do I make that relationship
known or access the field in my 'associate' model?
I didn't include hasMany relationship in the 'site' model because
there would be many. Do I need to do an inverse relationship in
other models? Examples I've seen don't all show the hasMany
relationships setup.
When I look at the models in ember inspector the site field is not
included in the model. Even if I wasn't getting the correct data
should it still show up?
I like ember so far, just need to understand and get over this roadblock
Update: My backend JSON library would only generate relationship links based on the current spec which would be
"related": "/streams/1/site"
but ember data does call
"related": "/sites/1"
to resolve the relationship
So #Adam Cooper answer is correct if you generate links as he answered or if you can only generate the links based on the current specification.
If you're using the JSONAPIAdapter, which is the default, you want your response to look this:
{
"links": {
"self": "/maint/associates"
},
"data": [{
"type": "associate",
"id": "1",
"attributes": {
"last": "Yoder",
"first": "Steven",
"active": "1"
},
relationships: {
"site": {
"links": {
related: "/sites/6"
}
}
}
}]
}
That will allow Ember Data to look up the site via its relationship. Right now Ember is trying to access the site model which Ember Data can't populate hence the error you're getting. As an aside you could probably do with returning an actual boolean value for active too.
I'm working on an Ember app that consumes an external API and I'm having trouble with my serializer.
My app is ingesting a user account but only cares about the very basics of the user account. The API is publishing much more data, which is causing trouble. Specifically, it is including a relationship to a model which I don't include in my Ember App (because it is domain-inappropriate).
I'm trying to configure my app such that it simply ignores the included and relationship information from the API, but even attempting to delete them from the response in the serializer's normalize hook isn't working. It keeps trying to look up the unwritten model and, obviously, failing. As well, I looked at using DS.EmbeddedRecordsMixin but that seems to still depend on having the related model implemented in my app, which I'm really hoping to avoid!
How do I get JSONAPISerializer to ignore relationships and prevent it from attempting to sideload data from the included object?
To better display my situation, here is an example payload:
{
"jsonapi": {
"version": "1.0"
},
"included": [
{
...references models my app doesn't have
}
],
"data": {
"type": "account",
"relationships": {
"permissions": {
"data": [
...references the included object
]
},
},
"id": "16",
"attributes": {
...this is the information I *do* care about
}
}
}
ETA:
My User model:
// app/models/account.js
export default Model.extend(Validations, {
birthdate: attr('date'),
email: attr('string'),
firstName: attr('string'),
lastName: attr('string'),
profile: belongsTo('profile')
}
There must be a value set in "selected" attribute before typing in search parameter".Can anyone help me to sort this out ? #ember-power-select
It is working with normal action-handling by setting a value for "destination" in js and assigning "destination" to "selected". Have a look at here for such examples http://www.ember-power-select.com/docs/action-handling.
But can't assign a value for custom-serach-action http://www.ember-power-select.com/docs/custom-search-action.
My Code:
Models:
hpqualifcation.js
import DS from 'ember-data';
export default DS.Model.extend({
type_name: DS.attr('string'),
hoprofile: DS.belongsTo('hoprofile')
});
hoprofile.js
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
hpqualification: DS.hasMany('hpqualification')
});
Route:
import Ember from 'ember';
export default Ember.Route.extend({
model: function(params){
return Ember.RSVP.hash({
hpqualifications: this.store.query('hpqualification', {username: params.username}),
…
});
}
})
Data from API side:
{
"hpqualification": [
{
"id": 1,
"type_name": "UG",
"hoprofile": 1
},
{
"id": 1,
"type_name": "PG",
"hoprofile": 2
}
],
"hoprofile": [
{
"id": 1,
"name": "silicon guy",
"hpqualifications": [1]
},
{
"id": 2,
"name": "power star",
"hpqualifications": [2]
}
]
}
Templates:
Used ember-power-select custom-search-action, where the request will be sent to API side for typing each letter and the data returned will be displayed in select box options http://www.ember-power-select.com/docs/custom-search-action
{{#each model.hpqualifications as |hpqualification|}}
{{#power-select
selected=hpqualification.hoprofile.name
search=(action "hoProfile")
onchange=(action (mut hpqualification.hoprofile.name))
as |repo|
}}
{{repo.name}}
{{/power-select}}
{{/each}}
{{/power-select}}
{{/each}}
Components:
import Ember from 'ember';
export default Ember.Component.extend({
actions: {
hoProfile(term){
if (Ember.isBlank(term)) { return []; }
const url = `//localhost:3000/betaweb/filters/hoprofiles? name=${term}`;
return Ember.$.ajax({ url }).then(json => json.hoprofiles);
}
}
});
Data returned for power-select action:
{
"hoprofiles": [{
"id": 7,
"name": "silicon guy"
}, {
"id": 14,
"name": "power star"
}]
}
Everything is working fine. But in ember-power-select the preselected value is not getting selected. The select box is blank before typing in search parameter .
normally using the below code the value is visible
{{#each model.hpqualifications as |hpqualification|}}
<label>HO Profile Name<label>
<li> {{input value=hpqualification.hoprofile.name}} </li>
{{/each}}
It displays all the data that is returned from API side.
HO Profile Name
- silicon guy
- power star
But when i use ember-power-select the data is not getting preselected in select box. I have tried many ways but it didn’t sort me out. Can anyone please get me a solution or an alternate way to do this using power-select ?
For prefilled data, you need to specify the options property as well.
From the docs:
"You can provide both options and a search action. Those options will be the initial set of options, but as soon as the user performs a search, the results of that search will be displayed instead."
Just make sure that the list you pass to the options is also formatted the same as the search results, in other words array of objects with a "name" attribute.
As for pre-selected object, your selected property needs to also be an object with a "name" attribute. In your case selected=hpqualification.hoprofile.
I'm relatively new to Ember CLI and have just begun to use ember-data to retrieve JSON data from my Laravel Eloquent-powered RESTful API.
I would like to populate a DataTables table with the data returned from the "Accounts" API. Each "Account" also has an embedded "Contact" record available under the "contact" key in the JSON returned from the server. The JSON is correct and an example of an "Account" record coming back from the API is:
{
"accounts": {
"id": 1,
"account_name": "My Account",
"contact": {
"id": 54,
"first_name": "John",
"last_name": "Smith"
}
}
}
In my controller I have called the serialize() method on each "Account" DS.Model in the RecordArray to convert it to a JSON object because this should allow relationships to be serialized too. However, even though I am using the ActiveModelSerializer with the EmbeddedRecordsMixin the relationships in the resulting JSON appear like this:
"contact": {
"id": "54"
}
So only the "id" field is present in the serialized, embedded "Contact" object.
My "account.js" serializer looks like this:
import DS from "ember-data";
export default DS.ActiveModelSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
contact: {embedded: 'always'},
},
});
and my "account.js" model looks like this:
import DS from 'ember-data';
export default DS.Model.extend({
contact: DS.belongsTo('contact', {embedded: 'always'}),
});
I cannot understand what I am doing wrong and I'd be grateful of any help anyone could offer.
Thanks.