Unable to access multiple nodes of model object in handlebarjs template - ember.js

I have posted my code here.
Here i am trying to access data of inner node of fixture but it is not working and it is showing blank results.
template code :
<ul>
{{#each item in model}}
{{#each item in item.list}}
{{#each item in item.contents}}
<li>{{item.product_name}}</li>
{{/each}}
{{/each}}
{{/each}}
</ul>
Can anyone tell me how to access data of inner node of object in template using each helper?
I have updated my code here.
Here i am getting data of first node of home_products i.e.
"contents": [
{
"id": "1",
"product_name": "abc11"
},
{
"id": "2",
"product_name": "abc12"
}
]
Failed to get data of second node i.e.
"contents": [
{
"id": "1",
"product_name": "abc21"
},
{
"id": "2",
"product_name": "abc22"
}
]
every time i am getting same data i.e. data of first node.
Can any one help me to solve this issue?

You need to change your template name to index to match the route where the data is returned by model hook:
// that route belongs to index template
Astcart.IndexRoute = Ember.Route.extend({
model: function() {
return Astcart.Application.find();
}
});
Just change the template to:
<script type="text/x-handlebars" data-template-name="index">
And change the mapping of the Astcart.Contents to product_name instead of name. To match with your fixture:
Astcart.Contents = Ember.Model.extend({
product_name: Ember.attr()
});
Fixtures:
...
"contents": [
{
"product_name": "abc",
},
{
"product_name": "pqr",
}
]
...
Working example http://jsfiddle.net/marciojunior/NKTcc/

Related

Ember power select to sort table results

I currently have a route servicerequests.index. In this route I am displaying a table of all service requests that I am getting via this call in my route:
model() {
return this.store.findAll('servicerequest').then(results =>
results.sortBy(this.get('selectedFilter')).reverse());
}
In my hbs file I have this power select:
{{#power-select options=filterOptions placeholder="Select a filter"
selected=selectedFilter onchange=(action (mut selectedFilter))
searchField="filterOptions" as |filter|}}
{{filter.descr}}
{{/power-select}}
In my controller I am defining the options:
filterOptions: [
{ descr: "created_at" },
{ descr: "priority" },
{ descr: "status" }],
actions: {
selectedFilter(filter) {
this.set('selectedFilter', filter);
}
},
What I want to happen is that when I select the different filter sort options to reorder the results on the page. How do you go about doing that?
With the data coming from the route and the options set in the controller I wasn't sure where to do the logic of the power selected.
Any thoughts or suggestions are appreciated.
Use a computer property in the controller for the sorting. Don't do it in the model hook.
My answer here is very related to this.
basically do this in your route:
model() {
return this.store.findAll('servicerequest');
}
and then in your controller:
filtetedModel: computed('selectedFilter', 'model.#each.{created_at,priority,status}', {
get() {
return this.model.sortBy(this.selectedFilter);
}
}),
filterOptions: [
{ descr: "created_at" },
{ descr: "priority" },
{ descr: "status" }
],
actions: {
selectedFilter(filter) {
this.set('selectedFilter', filter);
},
}

Ember-data return a single json object with store.find

Is this possible? I know I can do:
this.store.find('model', 1)
but that's not what I want. I would like to retrieve the json in this format: (working if I retrieve it in the route like this ):
App.OptionsRoute = Ember.Route.extend({
model: function () {
return {
"options":{
"id": "1",
"headline": "A Headline",
"results": [
{
"id": "1",
"title": 'Option 1',
},
{
"id": "2",
"title": "Option 2"
}
]
}
};
}
});
options model:
App.Options = DS.Model.extend({
headline: DS.attr(),
results: DS.attr()
});
options.hbs
<h5>{{options.headline}}</h5>
{{#each item in options.results}}
<h5>{{item.title}}</h5>
{{/each}}
I am using the RESTAdapter. And that is the only model that will be retrieved on that route. I would like to be able to use ember-data, but store.find expects an array.
You're missing a point here. First of all you're using bad format for your response. You need custom serializer. You can also use a bit more dirty workaround like this(but it works). Route:
App.OptionsRoute = Ember.Route.extend({
model: function() {
that = this;
return new Promise(function (resolve, reject) {
url = that.store.adapterFor('option').buildURL('option');
Ember.$.getJSON(url).then(function (json) {
body = json.options;
correct = {
options: [
body
]
};
that.store.pushPayload('option', correct);
resolve(that.store.all('option').get('firstObject'));
});
});
}
});
Template:
<h5>{{model.headline}}</h5>
{{#each item in model.results}}
<h5>{{item.title}}</h5>
{{/each}}
Application outputs:
A Headline
Option 1
Option 2
Working demo - please notice that I'm using $.mockjax to recreate your response from server, but it matches format you provided.

EmberJS auto loading inverse relations?

I have a model like:
var Survey = DS.Model.extend({
title: DS.attr('string'),
});
and:
var SurveySection = DS.Model.extend({
survey: DS.belongsTo('survey', {async:true}),
title: DS.attr('string'),
help_text: DS.attr('string'),
});
If i have a survey object, can I just do survey.get('survey_section') to get all the sections associated with a particular survey, because this isn't working? It doesn't even work if I add a survey_sections: DS.hasMany('survey_sections', {async:true}) to my survey model.
I should add that I'm using fixtures. When I release the app they'll still be used (ie so if the RESTAdapater would fix it, that's not a fix in my case):
Survey.reopenClass({
FIXTURES: [
{
"id": 1,
"title": "Favourite food"
},
{
"id": 2,
"title": "Sports"
}
]
});
and:
SurveySection.reopenClass({
FIXTURES: [
{
"help_text": "",
"id": 1,
"survey": 1,
"title": "Italian food"
},
{
"help_text": "",
"id": 2,
"survey": 1,
"title": "Team sports"
}, ...]});
Is the fixture adapter not able to retrieve related records in the reverse direction like this? If not, will I have to go the laborious route of manually getting the sections with survey=1, for example (laborious because I'll have to take this approach throughout my whole app with other models)?
Update
Specifically my failing code is (with survey 1):
this.get('survey').get('survey_sections').then(function(survey_sections) {
// survey_sections contains no objects, so objectAt(0) returns undefined.
survey_sections.objectAt(0).get('questions').then(function(questions) {
console.log('Set first question ID to ' + self.get('firstQuestionId'));
});
});
As the fixtures show there should be 2 SurveySection objects in survey_sections, but instead none are found.
I didn't want to do it, but I had to add the forward relation to the items in the Survey fixture, e.g.:
Survey.reopenClass({
FIXTURES: [
{
"id": 1,
"title": "Favourite food",
"survey_sections": [1, 2],
},
{
"id": 2,
"title": "Sports",
"survey_sections": [3],
}
]
});
and update the Survey model with:
survey_sections: DS.hasMany('survey_sections', {async:true})

How to parse nested arrays in a model in emberjs

I'm having trouble figuring out how to parse some json data from our backend server.
To start of, here's the data it returns:
{
"newsitem": {
"id": "1",
"title": "Some title",
"images": [
"IMG_0147.JPG",
"desert1.jpg"
],
"videos": [
"AEOpX8tmiUI",
"kxopViU98Xo"
]
}
}
I'm trying to parse this in my model:
App.Newsitem = DS.Model.extend({
title: DS.attr('string'),
images: DS.attr('array'),
videos: DS.attr('array')
});
But this give me an error that 'array' is not supported. How should I go with parsing this data and how should I print out the values of images and videos in the DOM through a handlebars template? I'm looking for a best-practise answer.
A lot of credits to nerdyworm on the #emberjs channel for the answer: you have to create your own serialize/deserialize methods for your new data type like this:
DS.JSONTransforms.array = {
serialize: function(jsonData) {
return Ember.typeOf(jsonData) == 'array' ? jsonData : [];
},
deserialize: function(externalData) {
return Ember.typeOf(externalData) == 'array' ? externalData : [];
}
}
Then in your handlebars template you can do:
<script type="text/x-handlebars" data-template-name="newsitem">
<div class="detail">
{{#each image in images}}
{{image}}<br/>
{{/each}}
</div>
</script>

How should I iterate over an array in emberjs and update the route to reflect the change?

I'm trying to make an image slideshow with next/previous buttons but I don't understand how I should make it work all together. Can someone help me glue the pieces?
This is how the data looks like:
{
"newsitems": [
{
"id": "1",
"title": "Amai het wordt bangelijk!",
"mediaitems": [
{
"id": "AEOpX8tmiUI",
"newsitem_id": "1",
"value": "AEOpX8tmiUI"
},
{
"id": "kxopViU98Xo",
"newsitem_id": "1",
"value": "kxopViU98Xo"
},
{
"id": "1",
"newsitem_id": "1",
"value": "1276468632.JPG"
},
{
"id": "3",
"newsitem_id": "1",
"value": "1278286227.jpg"
}
]
}
]
}
I'd like to let the user iterate the mediaitems array. So when the user enters a route:
http://domain.com/#!/newsitems/1/overlay/kxopViU98Xo
That item should be in the center of the screen and a next/prev button should take the user to the next or previous item in the array.
This is how my route looks like:
App.MediaitemRoute = Ember.Route.extend({
model: function(params) {
return App.Mediaitem.find(params.mediaitem_id);
},
setupController: function(controller, model) {
this.controllerFor('overlay').set('content', model);
},
renderTemplate: function(controller, model) {
this.render('overlay', { into: 'application', outlet: 'overlay', controller: 'overlay'});
}
});
And this is the ObjectController for the overlay:
App.OverlayController = Ember.ObjectController.extend({
prev: function(){
var mediaitems = this.get('model').get('newsitem.mediaitems');
var currentMediaItemID = this.get('model').get('id');
var currentIndex = 0;
var i = 0;
mediaitems.forEach(function(object){
if(object.get('id') == currentMediaItemID) currentIndex = i;
i++;
});
// How should I transition to the next object?
}
});
The route renders a template called "overlay' which has two actions: "prev" and "next" (I'm only showing prev in my controller to keep things clean).
My two concerns are: the code to lookup the currentitem in the array (and code to get the next or previous object) just feels 'wrong' or overly 'complex'.
I don't know how to update the route and redirect to the next/previous item.
Some more useful stuff:
Handlebars template:
<script type="text/x-handlebars" data-template-name="overlay">
<div class="overlay">
<a {{action "prev" target="controller"}}>PREV</a>
<a {{action "next" target="controller"}}>NEXT</a>
</div>
</script>
My models:
App.Newsitem = DS.Model.extend({
title: DS.attr('string'),
mediaitems: DS.hasMany('App.Mediaitem')
});
App.Mediaitem = DS.Model.extend({
value: DS.attr('string'),
newsitem: DS.belongsTo('App.Newsitem')
});
My routes:
App.Router.map(function(){
this.resource('newsitems', function(){
this.resource('newsitem', {path:':newsitem_id'}, function(){
this.resource('mediaitem', {path:'/overlay/:mediaitem_id'});
});
});
});