I'm using the ember-data last version with an important problem I 'm trying to solve.
The find function by id works perfect and the proper record is loaded into the Data Store so I can obtain the attributes that I want in the template for render them.
App.PostRoute = Ember.Route.extend({
model: function(params) {
return this.store.find('post', params.post_id);
}
});
On the other side, the findAll function doesn't work for me and the problem is Ember doesn't throw any error. In addition, Ember doesn't load any record and besides that I don't know how to iterate over the RecordArray returned in the template.
App.PostsRoute = Ember.Route.extend({
model: function() {
return this.store.find('post');
}
});
Any suggestions? Thanks for the help.
From your comment above, if your response looks like:
[
{"id":"1","attribute1":"value1", ...,"attributen": "valuen"},
{"id":"2","attribute1":"value1", ...,"attributen": "valuen"}
]
and you have not provided a custom serializer that modifies your response in extractArray(...), then data will not get processed because Ember Data expects something like:
{
"pluralizedModelName": [
{"id":"1","attribute1":"value1", ...,"attributen": "valuen"},
{"id":"2","attribute1":"value1", ...,"attributen": "valuen"}
]
}
See the Ember Data 1.0 specific code: https://github.com/emberjs/data/blob/master/TRANSITION.md#rest-adapter-and-serializer-configuration
How are you referencing the model in the template? Are you using the generated controller, or defining it yourself?
Also, the RecordArray should be automatically resolved by your Handlebars template. Try referencing {{#each}}. By default, your template will look for the property on the controller and if not found, bubble up to the model. If you can, create a JSBin (emberjs.jsbin.com) and we can collaborate with an example.
Edit: Also, are you using Fixture or Rest Adapter?
Related
I have a backend that follows the JSON API specification.
In my Ember app, I do something like this:
model() {
return this.store.query('category', { filter: { forum: 'main' } });
}
This works well and the request sent to the server is GET /categories?filter[forum]=main. My app gets all the categories from the forum with ID main.
Now, instead of the previous request, I would like to make a GET /forums/main/categories from the model. How can this be done in Ember with Ember Data?
Here's something I tried with Ember AJAX:
ajax: Ember.inject.service(),
model() {
return Ember.RSVP.hash({
categories: this.get('ajax').request('/forums/main/categories'),
});
}
The request works and the correct data is returned from the server. But Ember Data just doesn't know about it and I can't use the model in my template. How can I make Ember AJAX work with Ember Data?
The Ember AJAX GitHub page proposes to write something like that:
import DS from 'ember-data';
import AjaxServiceSupport from 'ember-ajax/mixins/ajax-support';
export default DS.JSONAPIAdapter.extend(AjaxServiceSupport);
https://github.com/ember-cli/ember-ajax#usage-with-ember-data
But it doesn't seem to change anything.
Okay, /forums/main/categories looks a bit like a relationship link. Like forum is a model as well, and has a relationship categories. Is this right?
If yes, probably the best thing is to first fetch the forum and then the relationship. Maybe you already have the forum record? So something like this:
store.findRecord('forum', 'main').then(forum => forum.get('categories'));
However if you want to filter the categories based on a forum string, this is also possible. So basically you want to do this:
this.store.query('category', { filter: { forum: 'main' } });
But it should request /forums/main/categories instead of /categories?filter[forum]=main. This can be done with a custom adapter. Probably you just have to override urlForQuery:
urlForQuery(query, modelName) {
if(query.filter.forum)
const forum = query.filter.forum;
delete query.filter.forum;
return `/forums/${forum}/categories`
} else {
return this._super(...arguments);
}
},
I am using ember-cli and there is one controller which gets using a render helper and hence no route. Example
{{render 'ref-type' ref-type}}
Now inside the controller ref-type
export default Ember.Controller.extend({
actions{
isShown: function() {
var m = this.get('model'); //here model is undefined can i know why?
}
}
});
and model ref-type is
export default Ember.Object.extend({
getData: function(){
return 'xyz'; //data is returned hre
}
});
why am i not able to access model in the controller.
Adding a raw JSBin example
JSBIN
Should the model always be DS.Model.extend? i do not think so.
Also Instead of ref-type i have used 'sample' as the name, so that it is easier to understand
You never initialize your model. According to your JSBin example you must have property named sample in your TodosController. ember will not create an object by itself. I have edited your JSBin. It might not be the best approach but I tried to explain what is going on.
If you put log {{log sample}} just above your render helper you will notice that your sample property is already undefined.
Ive got little basic problem with ember.
Here is app: http://emberjs.jsbin.com/qivamuzu/5 (click test - working like a charm, because model is in memory - loaded in index page)
But when you try page #test directly http://emberjs.jsbin.com/qivamuzu/5#/test all the data disappear (and that's bad - does not fired index route and load model). I follow this question Why isn't my ember.js route model being called? but doesn't help me.
I need to use template with model in other templates - I use {{render index}} but I'm not sure what to use and how. Please help me I am stuck.
I'm a little unclear on exactly what you're trying to do.
If you're just trying to use the same model data with a different route (and template) then you can explicitly set the model data to be the same in the route definition:
App = Ember.Application.create();
App.Router.map(function() {
this.route('test');
});
var myModelData = ['red', 'yellow', 'blue'];
App.IndexRoute = Ember.Route.extend({
model : function(){
return myModelData;
}
});
App.TestRoute = Ember.Route.extend({
model : function(){
return myModelData;
}
});
Here's a working JSBin example:
http://emberjs.jsbin.com/qivamuzu/8/edit
EDIT: Additional Information That May Help
Okay, one more stab at it =) When you navigate directly to the test page there is no data because the TestRoute is using the model data from the IndexRoute which hasn't been loaded yet. What you can do is force the creation of the IndexController and model by initializing it from the ApplicationRoute which will always be invoked when you first go to any route in your application.
First you have to generate the controller since it doesn't exist yet.
this.generateController('index');
Then you can get the controller and set its model data:
this.controllerFor('index').set('model', ['red','green','blue']);
Here's a working fiddle and I actually tested it this time to make sure it works when you go straight to #/test. I removed the extra routes and things that aren't actually needed from my previous example.
http://emberjs.jsbin.com/qivamuzu/11#/test
I'm trying to build a Tweetdeck-like UI to arrange items from a central library into categories. I really need help wrapping my head around the canonical way of using Ember's router.
Essentially, I have a search UI, which allows the user to open zero or more categories simultaneously. The categories show a list of items, which the user can add to from a central library on the right. By completely ignoring the router and the URL, I have managed to hack together a semi-working proof of concept. Now I want to go back and try to do it the Ember way. Below is a high level sketch of what I am trying to accomplish:
If I understand correctly, the desired URL scheme would be a comma-separate list of model IDs that are currently open. I got a good idea of how to approach that from another question, How to design a router so URLs can load multiple models?.
Unfortunately, there are a few concepts I do not understand:
How do I construct my templates and router, such that the library is displayed with its own model and controller? I assume a named {{outlet}} is the way to go, but I am completely lost when it comes to the renderTemplate configuration. Or perhaps I should use {{render}} instead? In either case, I do not understand the router's role in this situation.
EDIT 1/28: I've added an updated fiddle that includes a standalone library route/template and documents my attempts to render it into the categories template. How does Ember expect me to give the library template its model when I try to embed it into another route? I've tried both {{outlet}} with renderTemplate and {{render}}, but in both cases, I am stuck when it comes to specifying the model.
Using renderTemplate:
App.CategoriesRoute = Ember.Route.extend({
renderTemplate: function() {
this.render('categories');
this.render("library", {
into: "categories",
outlet: "library",
controller: "library",
});
},
});
When my controller receives a request to open a category, how do I communicate that to the router? How is the hash path updated? Who is responsible for loading the appropriate model(s)? I assume I should start with transitionTo or transitionToRoute, but I do not understand the router's role here either. Specific questions:
How do I de-serialize multiple, comma-separated models from the URL? Do I just split on the comma or is there a better way?
Once I get the IDs from the URL, how do I make my model hook return multiple records? Do I just shove them all into an Ember array?
When the controller gets the ID of a new record to open, how do I communicate that to the router?
I've tried to work this out on my own and have read the Ember documentation many times, but I am afraid it is simply over my head. I put together a minimal (currently non-functional) fiddle to outline my thoughts and point out where I am stuck. I would appreciate any help anyone could offer.
this.render does not accept a model parameter, but you could pass the model through the controller property instead, this makes sense to do since the Controller is really a proxy for the model at any rate
App.IndexRoute = Ember.Route.extend({
var self = this,
notesController = self.controllerFor('notes').set('content', self.store.find('notes'));
renderTemplate: function() {
this.render('notes', {
controller: notesController,
into: 'index',
outlet: 'notes'
});
}
});
You could also try something like this from this link.
App.IndexRoute = Ember.Route.extend({
model: function() {
return Ember.RSVP.hash({
books: this.store.findAll('book'),
genres: this.store.findAll('genre')
});
},
setupController: function(controller, model) {
controller.set('books', model.books);
controller.set('genres', model.genres);
}
});
Here, they load multiple models into one route using Ember.RSVP.hash and then using setupController they set each model (Rails: instance variable?) individually.
I'm assuming using this method that you could load as many models as you needed.
I have a question regarding non id based dynamic segments in the ember router.
I am using Ember.VERSION : 1.0.0-rc.1
I have a nested resource, and I need to use a url parameter in the path instead of an id.
but the ajax call to the json api needs to request an id.
So in my handlebars template I have:
{{#each thing in controller}}
{{#linkTo 'thing' thing.url}}{{thing.name}}{{/linkTo}}
{{/each}}
The things route looks like this:
App.ThingsRoute = Ember.Route.extend({
model: function() {
return App.Thing.find();
}
});
and the router:
App.Router.map(function() {
this.resource('things', function() {
this.resource('thing', {path:':thing_url'});
});
});
How do I map the url to resolve to the things id?
Fred is right. The model hook takes a params argument. Here is a more complete example.
App.ThingRoute = Ember.Route.extend({
model: function(params) {
return App.Thing.find(params.thing_url);
}
});
If you have already loaded all Things then you can use all method to retrieve all existing models and findProperty method to find array item by specific property:
App.ThingRoute = Ember.Route.extend({
model: function(params) {
return App.Thing.all().findProperty('url', params.thing_url);
}
});
Note that this will not work if required model is not loaded - the findProperty returns undefined if model is not in array and no request to server will be generated.
The model method has a parameter that gets passed in which would be thing.url in this case so you shold be able to access it there.
Read dynamic model part here
http://emberjs.com/guides/routing/specifying-a-routes-model/