Emberjs Application Routes and Controllers - ember.js

Can someone explain why this works:
Code in App.js:
App.ApplicationRoute = Ember.Route.extend({
setupController : function (params) {
this.controllerFor('food').set('model', App.Food.find(params.food_id));
}
});
But the following won't, unless I explicitly declare App.FoodController = Ember.ObjectController.extend();
App.FoodRoute = Ember.Route.extend({
model : function(params) {
return App.Food.find(params.food_id);
}
});
This is the code I'm using in index.html and does not change between blocks of code
<script type="text/x-handlebars" data-template-name="application">
{{ outlet }}
</script>
<script type="text/x-handlebars" data-template-name="food">
{{name}}
</script>
Router:
App.Router.map(function() {
this.resource( 'foods' );
this.resource( 'food', { path : '/food/:food_id' } );
});

The code that you have shown seems OK. Here is a working fiddle that proves it:
http://jsfiddle.net/ebXeS/2/
The only thing wrong about the code is this part (which is excluded from the fiddle):
App.ApplicationRoute = Ember.Route.extend({
setupController : function (params) {
this.controllerFor('food').set('model', App.Food.find(params.food_id));
}
});
According to your Router definition, you should not have food_id in the parameters of your application route. More than that, you should access the controller for the food route in the uhm... FoodRoute. Read more about Ember and the way it does routing (http://emberjs.com/guides/).

Related

Ember How can i render a child route into his parent?

I'm new with Ember and trying to render the content into the category template. So, if I clicked on the category, it will show me details and list content in the category template. I have tested something, but it didn't work. I have searched for this problem, but I can't solve it. I hope you can help me.
best regards
app.js
TableNotices.Router.map(function() {
this.resource('tableNotices', { path: '/' }, function(){
this.resource('category', {path: ':id'}, function(){
this.route('contents');
this.resource('content', {path: '/content/:id'});
});
});
});
TableNotices.ContentsRoute = Ember.Route.extend({
model: function() {
return this.modelFor('category').get('contents');
}
});
TableNotices.Content = DS.Model.extend({
content: DS.attr('string'),
contentType: DS.attr('string'),
orderPos: DS.attr('number'),
category: DS.belongsTo('category')
});
TableNotices.Category = DS.Model.extend({
name: DS.attr('string'),
parent: DS.attr('number'),
picture: DS.attr('string'),
contents: DS.hasMany('content', {async:true})
});
index.html:
<script type="text/x-handlebars" data-template-name="category">
{{name}}
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="contents">
foobar
</script>
jsbin
In the route you can specify how to render the templates with renderTemplate.
TableNotices.ContentsRoute = Ember.Route.extend({
model: function() {
return this.modelFor('category').get('contents');
}
renderTemplate: function() {
this.render('contents', { // the template to render
into: 'category', // the template to render into
outlet: 'category', // the name of the outlet in that template
controller: 'contents' // the controller to use for the template
});
}
});
<script type="text/x-handlebars" data-template-name="category">
{{name}}
{{outlet "contents"}}
</script>
Although Aaron Renoir's answer will work, the best way to think of this is that because your routes are nested, your templates need to be nested as well. Ember will render each of the nested templates into the parent template when these nested routes are activated. This gives you a nice way to delegate different parts of your page to various templates which helps to keep the content organized.
Each of your "parent" templates will need an {{outlet}} for the child templates to be rendered into.

Filling Ember selection with data received from server

I would like to receive json data from server and then generate html selection tag in Ember. This is my handlebars template:
<script type="text/x-handlebars" data-template-name="application">
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="rankings">
{{view Ember.Select contentBinding="countries" optionLabelPath="countries.name" optionValuePath="countries.path"}}
</script>
and my Ember trunk
App.ApplicationAdapter = DS.RESTAdapter;
App.Router.map(function() {
this.route('rankings')
});
App.RankingsRoute = Ember.Route.extend({
setupController: function(controller, model) {
controller.set('countries', this.store.findAll('country'));
}
});
App.RankingsController = Ember.Controller.extend({
countries: []
});
App.Country = DS.Model.extend({
path: DS.attr('string'),
name: DS.attr('string'),
}
It is not working fine. I am not having any errors in console and template is not rendering with this route and controller. What can be wrong?
Ember.Select looks for data on your controller's model. You have the countries array set up outside of your content, so it will not be able to view the data.
Personally, I would do it in the following way, though there are a couple of different approaches you can take to get similar results:
App.ApplicationAdapter = DS.RESTAdapter;
App.Router.map(function() {
this.route('rankings')
});
App.RankingsRoute = Ember.Route.extend({
model: function() {
return {countries : this.store.findAll('country')};
}
});
App.RankingsController = Ember.Controller.extend({
});
App.Country = DS.Model.extend({
path: DS.attr('string'),
name: DS.attr('string'),
}

Binding model to template with emberjs

I am going to bind model to template with emberjs
<script type="text/x-handlebars" id="dashboard">
<div>
<span>this is user list</span>
<div>
{{render userinfo userinfo}}
</div>
</div>
</script>
<script type="text/x-handlebars" id="_userinfo">
{{#each model}}
<span>{{user}}
{{/each}}
</script>
App.Userinfo= DS.Model.extend({
user: DS.attr("string")
});
App.Userinfo.FIXTURES = [
{user:"user1"},
{user:"user2"},
{user:"user3"}
];
App.UserinfoView= Ember.View.extend({
});
App.UserinfoController = Ember.ObjectController.extend({
});
App.Router.map(function() {
this.resource('dashboard', {path: '/dashboard'}, function() {
});
});
App.DashboardRoute = Ember.Route.extend({
renderTemplate: function() {
this.render('dashboard', { // the template to render
controller: 'dashboard' // the controller to use for the template
});
}
});
App.DashboardController = Ember.ObjectController.extend({
});
When i go to /#/dashboard, Dashboard template is loaded.
In here, I have rendered userinfo.
I'd like to bind Userinfo Model to usersinfo template so that I display all users.
Help me, please.
The short: here a working jsbin.
The long: You hade slightly to much unnecessary going on in your code, basically this does the job:
First of all you had no redirect to your dashboard route, since it's your only route (at least as far I can see from your code) we redirect directly to it after entering the index route
App.IndexRoute = Ember.Route.extend({
redirect: function() {
this.transitionTo('dashboard');
}
});
I've removed the DashboardController since there is nothing to be done.
Then your DashboardRoute was missing the model hook to provide actually data for your dashboard template
App.DashboardRoute = Ember.Route.extend({
model: function(){
return App.Userinfo.find();
}
});
In the router map you don't need to define a path if the URL is the same name as your template name in your case it is the same dashboard
App.Router.map(function() {
this.resource('dashboard');
});
The userinfo model was correct
App.Userinfo= DS.Model.extend({
user: DS.attr("string")
});
But your fixtures where missing the id
App.Userinfo.FIXTURES = [
{id:1, user:"user1"},
{id:2, user:"user2"},
{id:3, user:"user3"}
];
Moreover you where using the render helper with a partial template _userinfo the correct way to render a partial is this
{{partial userinfo}}
As you can see we don't pass any additional parameters to it because the data will be made available trough your model hook. The partial helper uses the context and the data provided in the template it is rendered into, in your case the dashboard template, therefore the model hook is necessary.
Hope it helps.

Ember does not render after transition

I have just written extremly simple Ember app, built on top of the Rails app, working with Ember Data and displaying, creating and persisting just one entity type to the server. Everything with the latest tools (Ember v1.0.0-pre.4-134-gaafb5eb).
However, there is very strange problem I have encountered. My app has two views: entity list (index) and form for creating new entities. When I enter the index directly, everything displays OK. But when I go to the other view and then back to the list, the view is not rendered again. Where could be the problem?
I guess it might be caused by my (maybe incorrect) using new Ember router. So I'm pasting important (from my point of view) parts of the app here:
Router:
App.Router.map(function() {
this.resource('bands', function() {
this.route('new');
});
});
App.IndexRoute = Ember.Route.extend({
redirect: function() {
this.transitionTo('bands');
}
});
App.BandsRoute = Ember.Route.extend({
model: function() {
return App.Band.find();
}
});
App.BandsNewRoute = Ember.Route.extend({
renderTemplate : function(){
this.render('bands_new',{
into:'application'
});
}
});
Link back to list - which does not work:
App.BandsNewController = Em.ArrayController.extend({
cancel: function() {
this.transitionTo('bands');
}
});
Have a look at the whole app here: https://github.com/pavelsmolka/roommating
(It's hugely inspired by great https://github.com/dgeb/ember_data_example)
I don't believe it, but could it be bug in Ember itself?
I think your "render" call in your BandsNewRoute is messing things up.Try making things go more with Ember defaults. So I would refactor your app to do this:
(working fiddle: http://jsfiddle.net/andremalan/DVbUY/)
Instead of making your own render, all you need to do is create a "bands" template (it can be completely empty except for {{outlet}} if you want) and a "bands.index" template.
<script type="text/x-handlebars" data-template-name="application">
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="bands/index">
<h2>Bands Index</h2>
{{#linkTo bands.new}}New Band{{/linkTo}}
</script>
<script type="text/x-handlebars" data-template-name="bands">
<h1>Bands</h1>
<p>
{{#linkTo index}}Start Again{{/linkTo}}
{{#linkTo bands.new}}New Band{{/linkTo}}
</p>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="bands/new">
I'm in new band!
<a {{action "cancel"}}>Cancel</a>
</script>
Your routes also clean up really nicely this way:
App.Router.map(function() {
this.resource('bands', function() {
this.route('new');
});
});
App.IndexRoute = Ember.Route.extend({
redirect: function() {
this.transitionTo('bands');
}
});
App.BandsNewController = Ember.Controller.extend({
cancel: function() {
this.transitionTo('bands');
}
});
I hope that helps!

new ember.js routing: how to connect outlets?

I'm confused how to connect outlets with the new router approach.
index.html:
...
<script type="text/x-handlebars" data-template-name="application">
<h4>The application handelbar</h4>
{{! outlet 1}}
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="index">
<h4>The index handelbar</h4>
{{! outlet 2 and 3}}
{{outlet nav}}
{{outlet main}}
</script>
<script type="text/x-handlebars" data-template-name="main">
<h4>The main handelbar</h4>
</script>
<script type="text/x-handlebars" data-template-name="nav">
<h4>The nav handelbar</h4>
</script>
...
app.js:
...
App.Router.map(function(match) {
this.resource("index", { path: "/" });
this.route("test");
});
App.IndexController = Ember.Controller.extend({
});
App.IndexView = Ember.View.extend({
templateName: 'index'
});
...
This code renders outlet-1.
Questions:
Why is outlet-1 rendered? How are outlet-1 and "index" connected?
How can I connect outlet 2 and 3 to the same "index" site?
Thanks
miw
You need to specify this stuff in a route handler, using the renderTemplate method (or renderTemplates method, depending on your build).
What you're not seeing is that Ember is setting quite a few defaults for you already. In fact, the defaults set by Ember have allowed you to omit the entire route handler.
App.Router.map(function(match) {
this.resource("index", { path: "/" });
this.route("test");
});
App.IndexRoute = Ember.Route.extend({
renderTemplate: function() {
this.render();
/* this is the default, it will basically render the
default template, in this case 'index', into the
application template, into the main outlet (i.e. your
outlet 1), and set the controller to be IndexController.
*/
}
});
What you want is to render additional templates in the renderTemplate function, likeso:
renderTemplate: function() {
this.render("index");
// this renders the index template into the primary unnamed outlet.
this.render("navtemplate", {outlet: "nav"});
// this renders the navtemplate into the outlet named 'nav'.
this.render("main", {outlet: "main"});
// this renders the main template into the outlet named 'main'.
}
Hope this helps.
Ember automatically assumes / matches with IndexRoute, IndexController and IndexView. This is in the ember routing guide
To connect nested routes you can do it like this:
App.OtherRoute = Ember.Route.extend({
renderTemplate: function() {
this.render('otherTemplate', {
into: 'index',
outlet: 'nav'
});
}
});
Here is a more in depth answer from another question.