ember.js - render a template in router.js equivalent for controllers - templates

In ember, is there a way to render a template into an outlet from a controller to get the desired effect of:
this.render('some_template', {
into: 'template_name',
outlet: 'template_outlet'
});
Or better yet, call an action in router.js from a controller?

you can put a method in the corresponding route to the controller under the actions hash (Example: posts.index controller and posts.index route) and call it using send
posts.index controller
this.send('exampleAction', record);
posts.index route
actions: {
exampleAction: function(record){
console.log(record);
}
}

Instead of outlet, you can use a component:
<script type="text/x-handlebars" id="components/x-outlet">
{{ partial template }}
</script>
Then, in your controller, you can have a template property that you can pass to the component to display your template dynamically:
App.IndexController = Ember.ArrayController.extend({
template: function(){
return 'this_one';
}.property(),
actions: {
that_one: function(){
this.set('template', 'that_one');
}
}
});
Working example here
Not completely sure what you mean by
Or better yet, call an action in router.js from a controller?
but if you are just trying to transition into a different route, you can use the transitionToRoute() method (see here)

Related

Passing variables to modal in ember

I am following the Ember cookbook for rendering a route into a modal here: http://emberjs.com/guides/cookbook/user_interface_and_interaction/using_modal_dialogs/. This works, but I am not sure how to pass variables to my rendered view.
Specifically I want to load a 'users/filters' route into the modal, which has access to a jobTitles array. This is defined in my application route simply as this.store.find('jobTitle'). The problem is that this does not seem to be accessible from the users/filters controller or template. The users/filters route doesn't seem to be run at all because I am using the render method as follows:
App.ApplicationRoute = Ember.Route.extend({
actions: {
openModal: function(modalName) {
return this.render(modalName, {
into: 'application',
outlet: 'modal'
});
}
}
});
How can I pass this into the rendered modal? Many thanks.
One possibility would be to pass a controller to the modal rendering function:
App.ApplicationRoute = Ember.Route.extend({
actions: {
openModal: function(modalName, controller) {
return this.render(modalName, {
into: 'application',
outlet: 'modal',
controller: controller
});
}
}
});
With the above code call the openModal hook in your route's template and pass the controller name (the name, not the controller itself) of the route to it. This way you should be able to access all properties of the controller.

How to debug a missing view

From my router, I'm rendering a view:
App.MonthSummaryRoute = Ember.Route.extend({
events: {
selectTab: function(name) {
this.render(name, { into: 'month/summary', outlet: 'tab' });
}
}
});
As an example, name is "summaryCompany". If I add a
<script type="text/x-handlebars" data-template-name="summaryCompany">
<h2>Test template</h2>
</script>
this template displays. But I tried to add a view to handle the events:
App.SummaryCompanyView = Ember.View.extend({
didInsertElement: function() {
console.log('here');
}
});
and I'm not getting anything. What am I missing?
Could you provide your entire code selection, or a JSBin / JSFiddle?
Possible approaches:
What's in your month/summary template / route / view?
Maybe you can't call render from an event. What happens when instead of doing the render from inside selectTab you do it from the route's renderTemplate hook?
renderTemplate: function() { this.render("summaryCompanyView", { into: 'month/summary', outlet: 'tab' }); }
You can try seeing if the view is inserted at all: in web inspector, find the ember-id of the div corresponding to view (somethign like <div id="ember310" ...>, then access the actual view object via Ember.Views.views.ember310 (or whatever id). You can check the view's class and see if it's App.SummaryCompanyView or a generic Ember.View
Lastly, what happens if you remove the inlined-template and specify the template on the View object via templateName?

How Do I Add a View to An Ember Template So That Its Controller Is Injected

I am adding a view to a template using the following:
{{view NewsCMS.NewsItemView itemBinding="news_item" class="news-item" }}
It seems that Ember does not inject its controller automatically, so how should I inject a controller into this view?
I have a controller set up:
NewsCMS.NewsItemController = Ember.ObjectController.extend({
someAction: function() {
console.log("CLICKED");
}
});
Use the {{render}} helper instead of the {{view}} helper to automatically set up the controller context: https://github.com/emberjs/ember.js/blob/master/packages/ember-routing/lib/helpers/render.js

Ember.js: Inserting child resource's view into the main application's outlet

By default Ember inserts the view of a child resource into an {{outlet}} defined by a view of a parent resource. How do I override that ? i.e. insert the child view in the {{outlet}} defined by the application view. Why is this the default?
Usecase: There is a users resource, with a new route inside it. I want the new to show in the applications {{outlet}} rather than the parent resource's {{outlet}}.
App.Router.map(function(){
this.resource('users', function(){
this.route('new');
});
});
For each route we have a renderTemplate method that we can overload. This gives us full control over the rendering of the views.
For example, we can specify into which {{outlet}} the view will render with into:
(I assume this is your use case, but I'm a little absent-minded today.)
var UsersRoute = Ember.Route.extend({
renderTemplate: function() {
this.render('users', {
// Render the UsersView into the outlet found in application.hbs
into: 'application'
});
}
});
We can also specify the name out of outlet to render into using the outlet property:
var UsersRoute = Ember.Route.extend({
renderTemplate: function() {
this.render('users', {
// Render the UsersView into the outlet named "sidebar"
outlet: 'sidebar'
});
}
});
And of course we can use a combination of both to specify both the outlet's name, as well as where that outlet is found using the into property.

How to render multiple templates for a route in Router v2

my index template has two outlets, one for header, another for content. the template rendered in the content changes depending on the content being viewed.
In the old router, this could be done by calling connectOutlet on different controllers who owned that template. I can't figure out how to do the same in the new router.
any suggestions?
With my research, I came to this:
Say you have a router defined like this:
App.Router.map(function(match) {
match('/').to('index');
});
ApplicationTemplate:
<script type="text/x-handlebars">
{{outlet header}}
{{outlet}}
</script>
IndexTemplate:
<script type="text/x-handlebars" data-template-name="index">
{{outlet dashboard}}
{{outlet spaces}}
</script>
Now, What we want is that when user goes to the index router, the page should:
Render index into main outlet and header into header outlet of application template.
render dashboard, spaces template into Index Template.
To achieve this, we write the following code in indexRoute
App.IndexRoute = Em.Route.extend({
renderTemplate: function(controller, model){
//Render header into header outlet
this.render('header',{
outlet:'header'
});
//Render index into main outlet. If you comment out
//this line, the code below fails
this.render('index');
//by using into, we can render into the index template
//Note: The controller is optional.if not specified,
//ember picks up controller for the given template.
this.render('dashboard',{
outlet:'dashboard',
into:'index',
controller:this.controllerFor('somethingElse', App.TestModel.find())
});
//controller is SpacesController
this.render('spaces',{
outlet:'spaces',
into:'index'
});
}
});
you can use the renderTemplates function in the router to render mulitple views to name outlets:
renderTemplates:function () {
this.render('todos_list', {
into:'todos', //template name
outlet: 'todos', //named outlet
controller: 'listController' //controller you want to use
});
this.render('todos_test', {
into:'todos',
outlet: 'test',
controller: 'testController'
});
},
setupControllers:function (controller, model) {
this.controllerFor('list').set('content', listmodel.find());
this.controllerFor('test').set('content', testmodel.find());
}
The setupControllerControllerFor function will allow you to assign what we set as 'context' in the previous router.
In your template, you would name outlets just as before:
{{outlet list}}
{{outlet test}}
Hope this helps :)