Ember Model get is not a function - ember.js

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);
}

Related

Set multiple models in render function, with the possibility to observe, reboot and save each separately

i have a problem with Ember.RSVP.hash(). Models does not render in templates, observes not work with promise model, and promise does not function reload().
import Ember from 'ember';
export default Ember.Route.extend({
achievementMode: true,
params:[],
model(params){
this.set('params', params);
return params;
},
renderTemplate(controller, model){
var firstController = this.controllerFor('clients/'+model.first),
secondController = this.controllerFor('clients/'+model.second),
firstModel = this.getModel(model.first,model),
secondModel = this.getModel(model.second,model);
this.render('clients/'+model.first,{
outlet:'first',
controller:firstController,
model: Ember.RSVP.hash(firstModel)
});
this.render('clients/'+model.second,{
outlet:'second',
controller:secondController,
model: Ember.RSVP.hash(secondModel)
});
},
setupController: function(controller, model) {
this._super(controller, model);
this.controllerFor('clients').set('firstBlock', model.first);
this.controllerFor('clients').set('secondBlock', model.second);
},
getModel(modelName, params){
var model = {};
if(modelName === 'profile'){
model ['client'] = this.store.findRecord('user', params.user_id, { reload: true }),
model ['achievements'] = this.store.query('achievement', {'mode':this.get('achievementMode'),'user':params.user_id})
}
model ['params'] = params;
return model;
}
});
Have a rest adapter, and after request observes('params') not work, and params not render in template.
{{#each achievements as |achievement|}}
test
{{/each}}
and promise not have a function reload().
ember 2.2
any thoughts? how to implement plans?

How not to fire observer in controller when model is set in setupController?

I set an observer function for a model's attribute in a controller.
and It fires as soon as I enter the route for that controller.
And I know it's because of controller.set('model', model); in setupController. How can I prevent this?
I want to use observer to make another attribute changed when an attribute is changed.
But because of this behavior my logic leads to a bug.....
Route
MuteAdmin.NewRoute = Ember.Route.extend({
model: function() {
return this.store.createRecord(this.get('articleModelClassName'));
},
setupController: function(controller, model) {
controller.set('model', model);
this.store.find(this.get('categoryModelClassName')).then(function(categories) {
controller.set('categories', categories);
if (model.get('category') == null) {
model.set('category', categories.get('firstObject'));
};
}.bind(this));
},
deactivate: function() {
if(this.controller.get('isDirty')) this.controller.get('model').deleteRecord();
}
});
Controller
MuteAdmin.NewController = Ember.ObjectController.extend(MuteAdmin.Modelable, {
publicChanged: function() {
console.log('How can I prevent this from printing when entering its route?');
}.observes('public'),
actions: {
submit: function() {
var currentUser = this.get('currentUser');
var article = this.get('model');
article.set('author', currentUser);
article.save().then(function() {
this.set("flashSuccess", "Successfully Created.");
this.transitionToRoute('index');
}.bind(this), function() {
});
}
}
});
Probably not the Ember way, but when I needed to manipulate model and controller on setup I used a flag to indicate controller is setting up.
Something like this:
MyRoute = ProtectedRoute.extend({
setupController: function (controller, model) {
controller['settingController'] = true;
controller.setProperties({
'prop1Name' : val1,
'prop2Name': val2,
'propNName': valN
});
controller['settingController'] = false;
// Call _super for default behavior
this._super(controller, model);
}
});
MyController = Ember.ObjectController.extend({
anAfterChangeObserver: function() {
if(controller['settingController']){
return;
}
doSomethings();
}.observes('prop1Name')
});

When is the model attached to the controller?

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)

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);
// }
});

How do I use dynamic segments in EmberJS' 2.2 router?

I can't figure out how to create routes with dynamic segments in the new router API for EmberJS. I've spent a week on it and tried many things but it doesn't work. I am really frustrated at myself because I've gone through the docs, API and source code many times and cannot figure out how to make this work. I am dying for assistance.
I am trying to achieve the following routes:
/profile/:userId -> index
/profile/:userId/activity -> activity page
/profile/:userId/...
My router is set up like this
App.Router.map(function() {
return this.resource("profile", function() {
this.route("index", { path: '/:userId' });
this.route("activity", { path: '/:userId/activity' });
});
});
Then, whenever I try to link with the linkTo helper, I receive the following error: Uncaught More objects were passed than dynamic segments
<li>{{#linkTo "profile.index" user}}overview{{/linkTo}}</li>
If I don't include the user object, then I receive another error Uncaught Error: assertion failed: Cannot call get with 'id' on an undefined object. (obviously because there's no object to take the ID of)
If it's any helper, here are my route declarations
App.ProfileIndexRoute = Ember.Route.extend({
model: function(params) {
return Ember.Object.create({
id: 1
});
},
setupController: function(controller, model) {
return controller.set("content", model);
}
});
App.ProfileActivityRoute = Ember.Route.extend({
model: function(params) {
return Ember.Object.create({
id: 1
});
},
setupController: function(controller, model) {
return controller.set("content", model);
}
});
JSBin example
You can structure your routes with a little bit more nesting to get the URLs you desire (and you don't need to have a return statement in your router):
App.Router.map(function() {
this.resource("profile", function() {
this.resource("userprofile", { path: '/:userId' }, function() {
this.route("index", { path: '/' });
this.route("activity", { path: '/activity' });
});
});
});
and then set up your routes like this:
App.IndexRoute = Ember.Route.extend({
model: function(params) {
return [Ember.Object.create({
id: 1
})];
}
});
App.UserprofileIndexRoute = Ember.Route.extend({
model: function(params) {
console.log("userindex route", params);
return Ember.Object.create({
id: 1
});
},
setupController: function(controller, model) {
return controller.set("content", model);
}
});
App.UserprofileActivityRoute = Ember.Route.extend({
model: function(params) {
return Ember.Object.create({
id: 1
});
},
setupController: function(controller, model) {
return controller.set("content", model);
}
});
You can link to the /profile/1 page:
{{#linkTo userprofile.index user}}
or link to the /profile/1/activity page:
{{#linkTo userprofile.activity user}}