Using third party framework, I want set selected value.
Is there is any hook after view inserted into DOM in ember.js new router?
Agreed with Karl above. However, maybe you've just asked the question in a bad way. In the new router, you have the setupController, which is invoked when Ember moves into that route. So for example, if you move into /#/dashboard, then DashboardController, DashboardView, DashboardRoute will all be initialised.
Aside from the fact that you could use the didInsertElement on the DashboardView at this point, you have the setupController method which you can overwrite in the DashboardRoute. In here you can set-up the controller, and perhaps do whatever it is you're trying to do:
(The setupController will only be invoked when you enter the route, but the view won't have rendered by the time you're moving into it. For that you'll need didInsertElement and that's that. setupController is for setting up the controller, which can be thought of as an ever-persistent singleton.)
var DashboardRoute = Ember.Route.extend({
setupController: function(controller) {
// We're in the route, so let's do something now.
controller.set('myText', 'Add this to the controller!');
}
});
Related
I'm playing with ideas for making a drag and drop interface. I have multiple components that can be dragged into position over a grid. I will have a button that will allow the user to select different arrangements.
I want a function on the component that sets its position (quite simply with left and top). I want to be able to call this function when the component is inserted, and when a different arrangement is selected.
What I want to do is create an event in the route's controller. I then want each component to be able to listen for the event, and react as necessary. I'm afraid I don't understand enough to make this work. I've read the API, and a couple of questions on here (1, 2), but no luck.
Here's what I have...
The route's controller:
import Ember from 'ember';
export default Ember.Controller.extend(Ember.Evented, {
actions: {
callPosition: function(){
this.trigger('position');
console.log('Trigger set...');
},
})
And the component:
import Ember from 'ember';
export default Ember.Component.extend(Ember.Evented, {
didInsertElement : function(){
this.get('controller').on('position', this, this.position);
},
position: function(){
console.log('event heard by the component');
},
A few things I don't understand:
Have I added the Ember.Evented mixin correctly?
I've added the listener in the didInsetElement event as per the example. Is this the correct way to ensure the component will listen for the event throughout its lifetime?
What's the scope of the event? Can it only be listened for so long at we 'get' the controller that set it?
Your advice is a great help to this budding amateur!
You should not try to fire an event on components from the controller! What you should do is to pass the variables (left, top) and then register an observer on them on the component
sizeChanged: Ember.on('didInsertElement', Ember.observer('top', 'left' function () {
// arrange it
}))
Now you pass down these attributes when you call the component:
{{my-component top=myCoolDnDElement.top left=myCoolDnDElement.left}}
And the sizeChanged will automatically be called whenever the top or left attribute changes as well as on didInsertElement.
This question is not about components, but about controller/view pairs which are not longer part of ember.
Back then every controller had an associated view, which often lead to confusion when to place things on the controller and when on the view.
Back then the separation was between controllers and views, where controllers managed global and local state and views basically managed the rendering.
With the introduction of components this has changed. Components handle local state as well as the rendering for that. Basically every component is a view. But its not anymore magically coupled to a controller, but explicit called from the template. For global state services were introduced.
Today you should follow the DDAU (Data Down Actions Up) principle and pass all actions and attributes explicit to the components in the template.
Components call actions on the parent component and pass updatable attributes and callable actions to child components. Thats how you should handle it.
To explain the issue I'm facing, I have 2 routes : ApplicationRoute and SomeRoute. I would need to wait for ApplicationRoute to resolve before trying to do something with SomeRoute.
The call order I see in debug :
ApplicationRoute.model // which returns a promise
SomeRoute.model
SomeRoute.setupController
ApplicationRoute.setupController
What I would want :
ApplicationRoute.model // which returns a promise
ApplicationRoute.setupController
SomeRoute.model
SomeRoute.setupController
There's probably a detail I'm missing somewhere...
UPDATE
The reason I incist for the ApplicationRoute.setupController to be able before other routes is that I use this to initialize some others controllers.
App.ApplicationRoute = Ember.Route.extend({
model: function() {
return Ember.$.getJSON("api/settings");
},
setupController: function(controller, jsonSettings) {
this.store.pushPayload(jsonSettings);
this.controllerFor("foobar").set("content", this.store.all("foobar"));
this.controllerFor("foobaz").set("content", this.store.all("foobaz"));
this.controllerFor("foobam").set("content", this.store.all("foobam"));
}
});
For a transition to proceed, all models in the hierarchy must resolve. That's as it should be; we don't want to start doing application logic--which includes things that might be done in a setupController, at whatever level of the hierarchy--while the necessary models are still pending and the transition has not been finalized and might even still be aborted.
So if we agree that models are resolved in top-down order, which makes sense--after all, a child route's model hook might want to refer to this.modelFor('parent')--why is setupController called in reverse order, from the bottom up? I'm guessing there may be good reasons for this, including the rendering lifecycle, but in one important sense it doesn't really matter: a parent route's controller being set up properly is not a prerequisite for the child route's controller to be set up. The parent route's controller is not even directly accessible from the child route's controller unless you inject it. For more on this topic, see http://discuss.emberjs.com/t/why-is-setupcontroller-called-after-the-model-hook-of-nested-routes/2655/9.
As an aside, you use the expression "a route resolving", and seem to imply that calling setupController is a part of that resolution process, but it would be more correct to refer to "a route's model resolving", and that does not include the invocation of setupController, which is something that happens after all the models in the chain of routes have resolved and the transition finalized.
In the specific case shown in the update to your question, consider putting your setupController logic in an afterModel hook instead. Logically, what you are doing in setupController is not setting up the controller; it's manipulating and processing the model, and therefore rightfully belongs in one of the model hooks.
I've got a Controller which backs a view that's created via {{render "foo"}}. This Controller is a singleton because I'm not passing in a model in the {{render "foo"}} call, and {{render "foo"}} can be called from many different parts of the application. So in other words, the view for this controller (which gets embedded via {{render}}) will be removed and added to the DOM over and over again. Is there a way for the controller to know when the view is rendered on and removed from the screen?
You could try and implement the didInsertElement and willDestroyElement hooks on your Ember view. http://emberjs.com/api/classes/Ember.View.html#event_didInsertElement
Then inside that implementation, you can call a function on your controller.. for example:
didInsertElement: function() {
this.get('controller').callFunctionOnController();
}
I am new to Ember and I am not sure how to do things the Ember way so I turn to you.
My problem:
I have a sidebar, I created a View for it. I have two buttons on the sidebar for the moment. I added an action for each button on it. I am not sure if I should handle it on controller or on view. I want on clicking one of these button, a new view to be inserted that would open a pop up menu and also the button that called the action to remain in a selected state.
I am not very sure how to do this. I tried to target the view with the action but I can't have access to the target element or at least I don't know how to access it (tried this.$()).
What way do you suggest to follow?
User 'actions' are handled with methods on a Controller or a Route. You should put them in an actions hash:
App.MyController = Ember.ObjectController.extend({
actions: {
doSomething: function() {
// do it here
}
}
});
Ember manipulates the DOM and inserts views automatically based on resources and routes. If you don't want to use the router, you can manually control the view hierarchy, but I'd suggest getting more familiar with Ember routing before you try manual views.
If I were you, I'd create a Component that handled the button. You will have a reference to the DOM element in the didInsertElement callback: http://emberjs.com/api/classes/Ember.Component.html#event_didInsertElement
from ember.js documentation, for RC4:
LINKTO NOW GENERATES ROUTETO EVENTS
Previously, the {{linkTo}} helper caused the router to transition
without any hooks to affect that behavior. Thanks to the work of Alex
Matchneer, the {{linkTo}} helper now generates a routeTo event that
can be handled just like any other event in a controller or a route's
events object. The default behavior of transitioning to the specified
route remains unchanged.
I don't understand how I can use it. I tried to do something like this:
App.ApplicationController = Ember.Controller.extend
routeTo: -> alert "hello"
but it's never fired when i click a link.
My goal was rolling back transactions when i leave a route
This should have been in the blog post, but you need to enable a flag on the ENV object. This would work:
Ember.ENV.ENABLE_ROUTE_TO = true
That said, routeTo might be short-lived as the next iteration of the router API is fully realized. Most likely, all transitions will fire an event that can be intercepted to halt the transition, and likely the event will be called willTransition. But this is not 100% solidified, so be sure to subscribe to https://gist.github.com/machty/5647589 for the latest.
update
I also totally missed out on the other part of your question (or maybe it was updated later), but routeTo is not a property you define on the controller, but rather an event that gets fired on the routes. So instead of having it on the controller, you'd do
App.SomeRoute = Ember.Route.extend
events:
routeTo: -> alert "hello"
But you wouldn't want this on ApplicationRoute since that's where the default-installed routeTo handler lives to perform the transition for you. The whole purpose of routeTo is to catch the event on a leafier route and possibly prevent it from happening.
important caveat
Just want to reiterate that this is a very short-lived feature of the API (it was somewhat experimental anyway, hence the fact that it was wrapped in a flag). In the next iteration of the router API, routeTo will likely be replaced by a willTransition event, at which I'll update this answer.
If you want to roll back transactions when you leave a route, you can use the deactivate hook as detailed here: http://emberjs.com/api/classes/Ember.Route.html#method_deactivate
This is called just before the route exits.
Something like this:
App.MyFavouriteRoute = Ember.Route.extend({
deactivate: function() {
//roll back your transaction here
console.log('deactivating my favourite route');
}
});
Note that this isn't called if you simply change the model... ie: if you transition from /myFavourite/1 to /myFavourite/2 then deactivate won't be called.... however if you transition to /myFavourites then it will be called