I‘m trying to have a set of buttons in an {{#each}}<button>...</button>{{/each}} block, and to get the target values by an ID of the model ...
Let’s say there is a controller with model and action:
export default Ember.Component.extend({
Texts: [
{id: "1", name: "One", sample: "Hello!"},
{id: "2", name: "Two", sample: "Hello! Hello!"},
{id: "3", name: "Three", sample: "Hello! Hello! Hello! "},
],
theText: "Test",
actions: {
setText: function(id) {
var theText= this.get('Texts.sample', id);
this.set('theText');
console.log(theText);
}
});
and this in the template:
{{#each Texts as |Text|}}
<button {{action "setText" Text.id}}>{{Text.name}}</button>
{{/each}}
<span>{{theText}}</span>
... this is my idea, but all I get is an undefined ...
Define array properties in init method.
Use findBy method to get matching id row.
export default Ember.Component.extend({
Texts: undefined,
theText: "Test",
init() {
this._super(...arguments);
this.set('Texts', [
{ id: "1", name: "One", sample: "Hello!" },
{ id: "2", name: "Two", sample: "Hello! Hello!" },
{ id: "3", name: "Three", sample: "Hello! Hello! Hello! " },
]);
},
actions: {
setText: function(id) {
let result = this.get('Texts').findBy('id', id);
this.set('theText', result.sample);
console.log(result);
}
}
});
Related
In my Ember app, a survey belongsTo a user; a user hasMany surveys. In my template, I would like to display a list of surveys, and the name of the user that created them. For now, I am pushing side-loaded data into the store via the application route, and it is showing up in the ember inspector->Data. The survey info is displaying correctly in the template, but the corresponding user's firstName will not appear. Help/guidance appreciated.
survey.js (model)
import DS from 'ember-data';
export default DS.Model.extend({
user: DS.belongsTo('user', {async: true}), //tried without async as well
title: DS.attr(),
post: DS.attr()
});
user.js (model)
import DS from 'ember-data';
export default DS.Model.extend({
surveys: DS.hasMany('survey', {async: true}),
firstName: DS.attr()
});
application.js (application route)
export default Ember.Route.extend({
model() {
this.store.push({
data: [{
id: 1,
type: 'survey',
attributes: {
title: 'My First Survey',
post: 'This is my Survey!'
},
relationships: {
user: 1
}
}, {
id: 2,
type: 'survey',
attributes: {
title: 'My Second Survey',
post: 'This is survey 2!'
},
relationships: {
user: 1
}
}, {
id: 1,
type: 'user',
attributes: {
firstName: 'Tyler'
},
relationships: {
surveys: [1, 2]
}
}]
});
}
});
surveys.js (route)
export default Ember.Route.extend({
model () {
return this.store.findAll('survey');
}
});
surveys.hbs (template)
<ul>
{{#each model as |survey|}}
<li>
<strong>{{survey.title}}</strong> //This works
<br>
{{survey.post}} //This works
<br>
Author: {{survey.user.firstName}} //This does not work
</li>
{{/each}}
</ul>
SOLUTION - updated application.js
export default Ember.Route.extend({
model() {
this.store.push({
"data": [ //Added double quotes throughout to conform to documentation
{
"id": "1",
"type": "survey",
"attributes": {
"title": "My First Survey",
"post": "This is my Survey!"
},
"relationships": {
"user": {
"data": {
"id": "1",
"type": "user"
}
}
}
}, {
"id": "2",
"type": "survey",
"attributes": {
"title": "My Second Survey",
"post": "This is survey 2!"
},
"relationships": {
"user": {
"data": {
"id": "1",
"type": "user"
}
}
}
}
],
"included": [
{
"id": "1",
"type": "user",
"attributes": {
"firstName": "Tyler"
} //no need to include user's relationships here
}
]
});
}
});
Payload relationship part is not correct. Should be:
relationships: {
user: {
data: {
id: 1,
type: 'user'
}
}
}
Also I think "user" payload should be in "included" section.
JSONAPISerializer api
I have created FIXTURES using ember-model, but i am not able to use following node on template
"logged_in": {
"id" : "1",
"logged": true,
"username": "sac1245",
"account_id": "4214"
}
I have implemented belongsTo relation for this node but it throwing one error : Uncaught Error: Ember.Adapter must implement findQuery
Here i have listed my model code :
Astcart.Application = Ember.Model.extend({
name: Ember.attr(),
logo_url : Ember.attr(),
list: Ember.hasMany('Astcart.List', {key: 'list', embedded: true}),
logged_in: Ember.belongsTo('Astcart.Logged_in', {key: 'logged_in'})
});
Astcart.List = Ember.Model.extend({
name: Ember.attr()
});
Astcart.Logged_in = Ember.Model.extend({
id: Ember.attr(),
logged: Ember.attr(),
username: Ember.attr(),
account_id: Ember.attr()
});
Astcart.Application.adapter = Ember.FixtureAdapter.create();
Astcart.Application.FIXTURES = [
{
"id" : "1",
"logo_url": "img/logo.jpg",
"logged_in": {
"id" : "1",
"logged": true,
"username": "sac1245",
"account_id": "4214"
},
"name": "gau",
"list": [
{
"id" : "1",
"name": "amit"
},
{
"id" : "2",
"name": "amit1"
}
]
}
];
Template code :
{{#each item in model}}
{{item.name}}
{{item.logged_in.logged}}
{{/each}}
Router code :
Astcart.ApplicationRoute = Ember.Route.extend({
model: function() {
return Astcart.Application.find();
}
});
Can any one show me how to access data of above node in template?
Your current fixture have the logged_in data embedded:
Astcart.Application.FIXTURES=[
{
...
"logged_in": {
"id": "1",
"logged": true,
"username": "sac1245",
"account_id": "4214"
},
...
}
];
So the logged_in property mapping need the parameter embedded: true, to be able to find this data, as follow:
Astcart.Application = Ember.Model.extend({
...
logged_in: Ember.belongsTo('Astcart.Logged_in', {key: 'logged_in', embedded: true })
});
Without this it will try to query for the Astcart.Logged_in:
Astcart.Logged_in.find(1)
and because it doesn't have an adapter, will fail with the exception: Uncaught Error: Ember.Adapter must implement findQuery
You can see this working in that fiddle http://jsfiddle.net/marciojunior/8zjsh/
Can someone explain why the side loading in this case don't work, I dont get any errors but the followers are not rendered and when I try to check it in the setupController method using model.get('followers').content, I got an empty array.
This is the loaded JSON:
{
user: {
id: 1,
follower_ids: [2,3,4],
name: 'someUserName'
}
followers: [
{
id: 2,
name: 'someUserName'
},
{
id: 3,
name: 'someUserName'
},
{
id: 4,
name: 'someUserName'
}
]
}
and this is my User model
App.User = DS.Model.extend({
name: DS.attr('string'),
followers: DS.hasMany('App.User')
});
Unlike the guide shows, the key for the ids must be followers instead of follower_ids. So with a JSON look like this it works:
{
user: {
id: 1,
followers: [2,3,4],
name: 'someUserName'
}
followers: [
{
id: 2,
name: 'someUserName'
},
{
id: 3,
name: 'someUserName'
},
{
id: 4,
name: 'someUserName'
}
]
}
I have 3 emberData models:
App.Product = DS.Model.extend({
page_title: DS.attr('string'),
shop: DS.belongsTo('App.Shop'),
user: DS.belongsTo('App.User')
});
App.Shop = DS.Model.extend({
name: DS.attr('string'),
});
App.User = DS.Model.extend({
name: DS.attr('string')
});
and the JSON data looks like this:
{
products: [
{
id: "1",
page_title: "Product 1",
user_id: "1",
shop_id: "1",
},
{
id: "2",
page_title: "Product 2",
user_id: "2",
shop_id: "1",
}
],
users: [
{
id: "1",
name: "User 1"
},
{
id: "2",
name: "User 2"
}
],
shops: [
{
id: "1",
name: "Shop 1"
}
]
}
But when I load the data I got the following error:
Assertion failed: Your server returned a hash with the key shops but you have no mapping for it
Ok, the documentaion is very unclear about the fact that when you have a belongsTo relationship the key for the sideload must be singular not plural even if its a list. So the JSON has to look like this:
{
products: [
{
id: "1",
page_title: "Product 1",
user_id: "1",
shop_id: "1",
},
{
id: "2",
page_title: "Product 2",
user_id: "2",
shop_id: "1",
}
],
user: [
{
id: "1",
name: "User 1"
},
{
id: "2",
name: "User 2"
}
],
shop: [
{
id: "1",
name: "Shop 1"
}
]
}
I can't figure out how to output properties from related models into views. Models are defined like this:
Club Model
App.Club = DS.Model.extend({
name: DS.attr('string'),
slug: DS.attr('string'),
... // Rest of omitted attributes
province: DS.belongsTo('App.Province'),
city: DS.belongsTo('App.City'),
servicetable: DS.belongsTo('App.Servicetable'),
timetable: DS.belongsTo('App.Timetable'),
pricetable: DS.belongsTo('App.Pricetable')
});
Servicetable Model, which belongs to Club
App.Servicetable = DS.Model.extend({
labels: {
parking: 'Parking',
bikeParking: 'Aparcamiento para bicicletas',
shower: 'Duchas',
materialRenting: 'Alquiler de Material',
restaurantCoffeeshop: 'Restaurante/Cafetería',
shop: 'Tienda',
playschool: 'Guardería',
locker: 'Taquillas',
handicapped: 'Acceso minusválidos',
sauna: 'Sauna',
wifi: 'WiFi'
},
parking: DS.attr('boolean'),
bikeParking: DS.attr('boolean'),
shower: DS.attr('boolean'),
materialRenting: DS.attr('boolean'),
restaurantCoffeeshop: DS.attr('boolean'),
shop: DS.attr('boolean'),
playschool: DS.attr('boolean'),
locker: DS.attr('boolean'),
handicapped: DS.attr('boolean'),
sauna: DS.attr('boolean'),
wifi: DS.attr('boolean'),
club: DS.belongsTo('App.Club')
});
Now, the output for api/clubs/2 is the following. Note that servicetable is being sideloaded to reduce number of requests:
{
"club": {
"id": "2",
"name": "Club de P\u00e1del y Tenis Fuencarral",
"slug": "club-de-padel-y-tenis-fuencarral",
... // Rest of omitted attributes
},
"servicetable": {
"id": "2",
"club_id": "2",
"parking": "1",
"bike_parking": "0",
"shower": "1",
"material_renting": "1",
"restaurant_coffeeshop": "1",
"shop": "1",
"playschool": "0",
"locker": "0",
"handicapped": "0",
"sauna": "0",
"wifi": "0"
}
}
Finally, route and template:
App.ClubGeneralInfoRoute = Em.Route.extend({
setupController: function(controller) {
controller.set('content', App.Club.find(App.clubId));
}
});
<script type="text/x-handlebars" data-template-name="club/general-info">
<h1>Club Info</h1>
<label>Parking</label>
{{view Ember.Checkbox checkedBinding="content.servicetable.parking"}}
</script>
So when I load the page, I can see the template rendering as the <h1> is appearing, but the properties of Servicetable not.
Note that if I try to render direct Club attributes like name or slug in this template, they are working too.
Any suggestions?
If you're sideloading, you need to configure your adapter to do so.
DS.RESTAdapter.configure('App.Servicetable', {
sideloadAs: 'servicetables'
});
Next, you need to include the servicetable id in the club's json:
"club": {
"id": "2",
"servicetable_id": 2,
... // Rest of attributes
}
When you side load records, pass them as an array, and set the key in plural form:
"servicetables": [{
"id": "2",
... // Rest of attributes
}]
Finally, the complete json response should look like this:
{
"club": {
"id": "2",
"servicetable_id": 2,
"name": "Club de P\u00e1del y Tenis Fuencarral",
"slug": "club-de-padel-y-tenis-fuencarral",
... // Rest of attributes
},
"servicetables": [{
"id": "2",
"club_id": "2",
"parking": "1",
... // Rest of attributes
}]
}