I was fiddling around with Ember and I came across something that confused me.
I have an ArrayController (Index) with an item controller (Post). For the init hook on the Post item controller, I have it send a debug line out to the console. This debug statement is being sent twice for each post, and I can't figure out why.
Code on JSBin:
http://emberjs.jsbin.com/momikuto/14/edit
HTML:
<script type="text/x-handlebars">
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="index">
{{each controller itemViewClass="App.PostView"}}
</script>
<script type="text/x-handlebars" data-template-name="post">
POST {{id}}<br />
</script>
JavaScript:
App = Ember.Application.create();
App.IndexController = Ember.ArrayController.extend({
itemController: 'post',
templateName: 'index',
addPost: function (id) {
this.pushObject(App.PostController.create({ id: id }));
}
});
App.PostController = Ember.ObjectController.extend({
debug: function () {
console.log('init for post ' + this.get('id'));
}.on('init')
});
App.IndexView = Ember.View.extend({
didInsertElement: function () {
this.get('controller').addPost(1);
this.get('controller').addPost(2);
}
});
App.PostView = Ember.View.extend({
tagName: 'span',
templateName: 'post'
});
Output:
init for post 1
init for post 1
init for post 2
init for post 2
If I remove post 2 and only use post 1, I just get init for post 1 twice. If I add a post, I get all three of them twice. The number of Post objects in the ArrayControl does not seem to have anything to do with the problem.
I saw one post on the Ember Github, but it was closed after it was assumed to not be an Ember issue. Any ideas?
You're creating it twice. You have itemController set on your IndexController and you're actually creating the controller in the addPost function.
You shouldn't ever need to create a controller instance yourself, except for some strange edge cases. Ember will create the itemControler instance for you when you pushObject so you don't need to manually create.
Related
i just wanna refresh model in route while get an action from controller and run doRefresh action in this route
this is my code
import Ember from 'ember';
export default Ember.Route.extend({
profileFormService: Ember.inject.service(),
profileFormAtributeService: Ember.inject.service(),
model(){
return Ember.RSVP.hash({
profileForms: this.get('profileFormService').find(),
profileFormsAttributes: this.get('profileFormAtributeService').findByProfileFormId("1"),
inputTypes: {data: ['CHECKBOX', 'NUMBER_FIELD', 'PHONE_NUMBER', 'TEXT_FIELD', 'EMAIL', 'TEXT_AREA', 'RADIO_BUTTON', 'DESA', 'KABUPATEN_KOTA', 'PROVINSI', 'KECAMATAN', 'MAP_POINT', 'MAP_POLYGON']}
});
},
setupController(controller, model) {
this.controllerFor('backend.setting-profile-form-attribute').set('profileForms', model.profileForms);
this.controllerFor('backend.setting-profile-form-attribute').set('profileFormsAttributes', model.profileFormsAttributes);
this.controllerFor('backend.setting-profile-form-attribute').set('inputTypes', model.inputTypes);
},
actions:{
doRefresh(param){
let context = this;
this.get('profileFormAtributeService').findByProfileFormId(param).then(function (response) {
context.set("profileFormsAttributes",response);
}), function (e) {
this.debug(e);
};
}
}
});
unfortunately this is does'nt affect the profileFormsAttributes model.
I've ben trying to debug the model with this
this.debug(this.get('controller.model.profileFormsAttributes'))
this.debug(this.get('model.profileFormsAttributes'));
but the console log said undefined
can you resolve this and explain what happen in this my route..
thank's for your concern
Your problem is that you cannot achieve the object returned from within route in action handler directly like this.get('profileFormsAttributes'); hence your setting does not work.
this.get('controller.model.profileFormsAttributes');
this.get('model.profileFormsAttributes');
Even above two statements does not work; because you cannot retrieve model or controller like this.
You have two options; either you need to save what you are going to return from model directly within model hook with this.set('model', model) or you can achieve it with this.controllerFor(this.get('routeName')).get('model')
I would recommend the second approach for your case. Please take a look at the following twiddle that I have prepared to illustrate the case for you.
Please take a look at index.js where foo attribute of object returned from model hook is set with
Ember.set(this.controllerFor(this.get('routeName')).get('model'), 'foo', 'foo updated');
I hope this helps.
I have been using ember for a few days now, but i ran to this simple problem:
I made an ajax call and return the results to the model in the route. Basically the call will return a single json object. As i read in the guide, the model will be sent to the 'content' of the controller as below. The problem is how to get the data printed to the template? This is not working:
The Controller:
App.IndexController = Ember.ObjectController.extend({
content: [{name:'smith', age:'20',lastname:'jonnie'}]
});
Handlebars:
<p>{{name}}, {{age}}, {{lastname}}</p>
The content property is an array, so you rather loop over it to get your items out
template
<ul>
{{#each item in controller.content}}
<li>{{item.name}}</li>
{{/each}}
</ul>
or try something like this:
IndexController
App.IndexController = Ember.ObjectController.extend({
content: [{name:'smith', age:'20',lastname:'jonnie'}],
firstObject: Ember.computed.alias('content.firstObject')
});
template
<p>{{firstObject.name}}, {{firstObject.age}}, {{firstObject.lastname}}</p>
Working example.
Hope it helps.
I'm working with the latest release of Ember JS (RC1), and I have an architectural problem :
I have a very simple use case : a list of users, and a form to add users.
My Router:
App.Router.map(function () {
this.resource('users', function () {
this.route('new');
});
});
My Routes:
App.UsersRoute = Em.Route.extend({
model:function () {
return App.User.findAll();
}
});
My Controller:
App.UsersNewController = Em.ObjectController.extend({
saveUser:function () {
//'content' contains the user
App.User.save(this.content);
// here i want to reload the list of users, but it doesn't work
// The application goes correctly to the url /users
// But doesn't call the 'model' function
this.transitionToRoute('users');
}
});
As I say in the above comment, when I create a new User, I'd like to redirect to the list of users (that part works) AND reload the user list by calling the 'model' method of the route (that part doesn't).
I could write a method in UsersController to reload the list, but then I would have duplication between UsersRoute and UsersController.
Can someone help me on this problem ?
Thanks
P.S. : here a fiddle http://jsfiddle.net/vsxXj/
Ember Documentation on the model hook:
"A hook you can implement to convert the URL into the model for this
route."
So i do not think that this hook is right for this case. I think you should use the setupController hook for this case. Try this:
App.UsersRoute = Em.Route.extend({
setupController(controller){
controller.set("content", App.User.findAll());
}
});
this is my first post in stackoverflow.
I'm new to ember.js and i've been studying ember.js.
I'm building a small app to learn ember.js now,but binding doesn't work somehow.
Please give me a help!!
#------------------------Controller------------------------
App.ApplicationController = Ember.Controller.extend();
App.monstersController = Ember.ArrayProxy.create({
content:[],
//some code to add model instances to content...
counter: function(){
var content = this.get('content');
return content.get('length');
}.property('length')
});
#------------------------View------------------------
App.StatsView = Ember.View.extend({
counterBinding : 'App.monstersController.counter',
#------------------------HTML------------------------
<script type="text/x-handlebars" data-template-name="application">
//some code here
{{#view App.StatsView}}Counter: {{counter}}{{/view}}
//I'm expecting the length of content array in App.monstersController above.
//some code here
</script>
If you want to access a value off of a view you need to access it via {{view.counter}}.
However, in your case you should probably be setting the controller on the view like:
App.StatsView = Ember.View.extend({
controllerBinding : 'App.monstersController'
})
Once you get the hang of that, I'd look into setting up a router to manage binding controllers and views together.
As you'll be able to tell from my question, I'm slowly learning EmberJS. I've read the great guide on routes and I felt ready to take on the world but then...
In my example, I thought the {{somethingView}} would be rendered and not the controller property {{somethingCtrl}}. Is this the correct behaviour? If so how would you render a property from the Ember.View?
The JS
window.App = Ember.Application.create({
ready: function() {
this.initialize();
}
});
window.App.Router = Ember.Router.extend({
root: Ember.Route.extend({
index: Ember.Route.extend({
route: '/',
connectOutlets: function(router) {
var controller = router.get('applicationController');
controller.connectOutlet('garments');
}
})
})
})
window.App.ApplicationView = Ember.View.extend({
templateName: 'application',
});
window.App.ApplicationController = Ember.Controller.extend();
window.App.GarmentsController = Ember.Controller.extend({
somethingCtrl: "Something in the controller"
});
window.App.GarmentsView = Ember.View.extend({
templateName: 'garments',
somethingView: "Something in the view"
});
The DOM stuff
<script type="text/x-handlebars" data-template-name="application">
<h1>Hi Ember</h1>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="garments">
<h1>Garments</h1>
{{somethingView}}<br>
{{somethingCtrl}}
</script>
The Fiddle
This behaviour is correct. These are my understandings of these ember core concepts:
Model: These objects represent the date that is handled by your application. These are the business objects that form the domain model of your Application.
Controller: A Controller is responsible for providing access to your models. Controllers have the property content, where models should be injected (a single Object for Ember.Controller and an array of objects for Ember.ArrayController). The Controller passes this content to your View. The Controller is the default context for your view. Therefore the behaviour you describe is expected.
View: The View is just intended for displaying issues. I personally use it mainly to do jQuery animations.
But nonetheless it is possible to access the view instance in the template. You just have to use the variable with the name 'view' in your template. I updated your fiddle with a working example: http://jsfiddle.net/jPK8A/5/
<script type="text/x-handlebars" data-template-name="garments">
<h1>Garments</h1>
{{view.somethingView}}<br>
{{somethingCtrl}}
</script>
But to be clear: The most common case should be to access contents from your controller. It should be not often that you access variables of your view. You want to display date in your App and this date resides in models and should therefore be accessed through controllers. The most likely case might be, that you want to store labels in your view or something like that (labels that have to be computed).