When is the model attached to the controller? - ember.js

At what point is the model attached to the controller? And, is there a hook when the model is there?
Because I face the following problem of not being able to access the model to do some computations with the data in it:
App.ResultsRoute = Ember.Route.extend({
model: function(){
// LOCAL, blocking call!
return {messages : this.store.all('message').toArray()};
}
});
App.ResultsController = Ember.ObjectController.extend({
init : function(){
this._super();
console.log(this);
console.log(this.get('model'));
console.log(this.get('model.messages'));
this._someComputation();
},
_someComputation : function(){
this.get('model.messages').forEach(function(message){
//do something
}
}
});
This prints:
Class { [...] model: messages: Array[58]0: Class1: Class2: [...] Class57: Class length: 58}
null
null
So, basically I can see the model in the console but when accessing it programmatically in the init function it's not there (yet?).
Or is this is the wrong way (or place) to do some computations with the model data?
edit:
The controller of a child route can access the model, so this would work as a workaround:
App.ResultsIndexController = Ember.Controller.extend({
needs: "results",
parentController : Ember.computed.alias('controllers.results'),
init : function(){
console.log("ResultsIndexController created");
console.log(this.get('parentController').get('model'));
}
});
Prints:
ResultsIndexController created
{messages: Array[55]}
But I'd rather have it in the parent controller such that all children can access it.

it's attached during setupController which happens in the route, after init, when the model has been resolved. The code essentially looks like this:
App.ResultsRoute = Ember.Route.extend({
model: function(){
// LOCAL, blocking call!
return {messages : this.store.all('message').toArray()};
},
setupController: function(controller, model){
controller.set('model', model);
}
});
If you wanted you could do it during setupController, it's a fairly common practice to override it to add additional functionality.
App.ResultsRoute = Ember.Route.extend({
model: function(){
// LOCAL, blocking call!
return {messages : this.store.all('message').toArray()};
},
setupController: function(controller, model){
this._super(controller, model);
controller._someComputation();
}
});
Additionally your model hook says it's a blocking call, but you aren't returning a promise, so that isn't true (but maybe that's just a copy paste foo)

Related

Ember Model get is not a function

Why sometimes in setup controller on my product route, model.get('property') works and other times I have to retrieve properties with model.property
It throws an error
model.get( is not a function...
Why is this happening, clues?
Details :
Product Route -
model: function(params) {
return this.store.find('product', params.product_id);
},
setupController: function(controller, model){
this._super(controller, model);
var type = model.get('publisher').get('entity_type');
}
Index Route -
model: function(params){
return Ember.RSVP.Promise.all([
this.store.find('groupedItem', { group_code: 'HOME', position : 1 }),
this.store.find('groupedItem', { group_code: 'HOME', position : 2 }),
])
}
You're calling an asynchronous method in your setupController hook which Ember isn't expecting. You're probably trying to call model.get() before you've actually placed the model on the controller. That kind of asynchronous operation should be happening in the model() hook, not in the setupController() hook.
model: function() {
return Ember.RSVP.Promise.all([
this.store.find('groupedItem', { group_code: 'HOME', position : 1 }),
this.store.find('groupedItem', { group_code: 'HOME', position : 2 })
]);
},
// This is actually the default behavior of this method
// So you don't have to override it if you don't want to
setupController: function(controller, model) {
// The `model` is your `values`
controller.set('model', model);
}

Filtering RecordArray in a child route to return a RecordArray?

Im trying to my views change when a model property changes
Im not sure if I am on the right track or not, but here goes.
I have a parent resource called lunches, whose route looks like so:
model: function(params){
return this.store.filter('lunch', params, this.funcAll);
}
and I have a child route 'served', whose route looks like so:
model: function(params){
return this.modelFor('lunches').filterProperty('isServed', true);
// as opposed to this.store.filter('lunch', this.funcFilter()})
}
when I use filter in the child routes, I am able to do this (I think because a filter returns a RecordArray), but this does not work for me, for another reason. Is there anyway I can have my child route return a RecordArray which is a subset of the original model?
filter works on a collection.
App.ColorsRoute = Ember.Route.extend({
model: function() {
this.store.find('color');
return this.store.filter('color',function(){
return true;
});
}
});
App.ColorRoute = Ember.Route.extend({
model: function(params) {
return this.store.find('color', params.id);
},
setupController: function(controller, model){
this._super(controller, model);
var cMod = this.modelFor('colors'),
subItems = cMod.filter(function(item){
return item.get('color').indexOf('e')>=0;
});
console.log(subItems.get('length'));
}
});
http://emberjs.jsbin.com/OxIDiVU/858/edit

Multiple controllers for one view - request for the model not set

I got the following code:
App.ApplicationSerializer = DS.ActiveModelSerializer.extend({});
App.Router.map(function(){
this.resource('clients', { path : '/' });
});
App.ApplicationAdapter = DS.RESTAdapter.extend({
namespace: 'api'
});
App.ClientsRoute = Ember.Route.extend({
setupController: function(controller, model){
controller.set('model', model);
this.controllerFor('patients').set('model', this.store.find('patient'));
}
});
When the main page is loaded a request is sent only to localhost:3000/api/patients and not to clients which is the main controller for the given view :/
Can you spot the mistake? I am using App.ApplicationSerializer = DS.ActiveModelSerializer.extend({});
I thought that might be the error, but after removing it I saw no changes at all.
You are not defining the model for ClientsRoute:
App.ClientsRoute = Ember.Route.extend({
model: function() {
return this.store.find('client');
}
});
The only case where its not necessary to define the model, is when the route is a simple dynamic segment (show a specific record). Example:
App.Router.map(function() {
this.route('client', { path: '/clients/:client_id' });
});
App.ClientRoute = Ember.Route.extend({
// Default model (no need to explicitly define it):
// model: function(params) {
// return this.store.find('client', params.client_id);
// }
});

Ember, working with a model

I'm confused about how to set up retrieve information from my (dynamic) model in Ember.js
Here is my model (works so far):
App.Router.map(function() {
    this.resource('calendar', { path: '/calendar/:currentMonth'});
});
App.CalendarRoute = Ember.Route.extend({
model: function (params) {
var obj = {
daysList: calendar.getDaysInMonth("2013", params.currentMonth),
currentMonth: params.currentMonth
};
return obj;
}
});
I just want to get back the 'currentMonth' attribute:
App.CalendarController = Ember.Controller.extend({
next: function() {
console.log(this.get('currentMonth'));
}
});
But I am getting an "undefined" error.
Do I have to explicitly declare my model (Ember.model.extend()) in order to get and set values?
There are some conventions that you might not be aware of in regards to setting a Model into a Controller.
In a Route, model can be any object or collection of objects you define. There is a huge deal of conventions that apply and for most cases, you don't have to specify anything as it uses the names of various objects to guide itself on building the query and a set the content of your controller, however, in your particular code, you are return obj as the model.
Ember provides a hook called setupController that will set this object into your controller's content property. Example:
App.CalendarRoute = Ember.Route.extend({
model: function (params) {
var obj = {
daysList: calendar.getDaysInMonth("2013", params.currentMonth),
currentMonth: params.currentMonth
};
return obj;
},
setupController: function(controller, model) {
// model in this case, should be the instance of your "obj" from "model" above
controller.set('content', model);
}
});
With that said, you should try console.log(this.get('content.currentMonth'));

Computed property in handlebar #if not updating

I am trying to use the following template:
<script type="text/x-handlebars" data-template-name="login">
{{#if logged_in}}
Logged in
{{else}}
Not logged in
{{/if}}
</script>
with the model:
App.Login = DS.Model.extend({
access_token: DS.attr('string'),
logged_in: function() {
return (this.get('access_token') != null);
}.property('access_token')
});
to display the user's logged-in state.
The access_token is being set via an async callback in the Route's setupController:
App.LoginRoute = Ember.Route.extend({
setupController: function(controller, model) {
controller.set('content', model);
// call async login method
window.setInterval(function test() {
model.set('access_token', 'MY_ACCESS_TOKEN');
console.log(model.get('access_token'));
}, 5000);
},
model: function() {
return App.Login.find();
}
});
The problem is logged_in never seems to change (even though the model.set line is executed and 'access_token' is updated). Am I doing something wrong or should I be filing a bug?
Full code: http://jsfiddle.net/Q8eHq/
You are setting the model to App.Login.find() which returns an enumerable, not a single object. One way to do it, is to set the model to a single object:
App.LoginRoute = Ember.Route.extend({
model: function() {
return App.Login.find(1);
}
});
Or if you are going to use a dynamic route (e.g. users/login/9):
App.LoginRoute = Ember.Route.extend({
model: function(params) {
return App.Login.find(params.id);
}
});