Binding model to template with emberjs - templates

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.

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.

Two data sources and two outlets in ember.js

I'm trying to create something really simple with ember.js, and I'm getting badly lost between old examples, new examples, and extensive documentation.
I want to create an application with no functionality, that simply shows two sets of data in two columns. The real application uses JSON data from two different sources and is more complicated, but the problem reduces to getting the below to work:
<div id="appholder">
<script type="text/x-handlebars">
{{outlet left}}
{{outlet right}}
</script>
<script type="text/x-handlebars" data-template-name="left">
<div id="left">
<ul>
{{#each item in model}}
<li>{{item}}</li>
{{/each}}
</ul>
</div>
</script>
<script type="text/x-handlebars" data-template-name="right">
<div id="right">
<ul>
{{#each item in model}}
<li>{{item}}</li>
{{/each}}
</ul>
</div>
</script>
</div>
and in the javascript something like
App = Ember.Application.create({
rootElement: '#appholder'
});
App.LeftController = Ember.ArrayController.extend({
model: function() {
return ['left one', 'left two'];
}
});
App.RightController = Ember.ArrayController.extend({
model: function() {
return ['right one', 'right two'];
}
});
App.IndexRoute = Ember.Route.extend({
renderTemplate: function() {
this.render('left', {
outlet: 'left',
controller: 'left',
});
this.render('right', {
outlet: 'right',
controller: 'right',
});
}
});
to output the hoped for result, a left column with list entries from one data source and a right column with two entries from another column.
Could somebody ideally provide a js fiddle with the above adapted to working code? Any part of it can change, to use {{render}} or {{view}} in the templates and whatever the js should be.
Thank you for any help
http://emberjs.jsbin.com/mifer/2/edit
Here is a working JSBin
First in order to use a function as a property, you must make it a computed property with the property() function:
App.LeftController = Ember.ArrayController.extend({
model: function() {
return ['left one', 'left two'];
}.property()
});
Secondly, the renderTemplate code is in the wrong place. You put it in the index route but in reality it should be in the application route. If you had {{outlet}} in your application template, the index template would have been rendered into it. Then, if you had those two named outlets inside the index template, what you had would have almost worked (you need to call this.render() or this._super() whenever you use renderTemplate if you want the route template to render.
But, you have two named outlets which you want to manually render into inside of your application template. Hence:
App.ApplicationRoute = Ember.Route.extend({
renderTemplate: function(){
this.render();
this.render('left', {outlet: 'left', into: 'application'});
this.render('right', {outlet: 'right', into: 'application'});
}
});
Now this next approach is how I tackle multiple models in my dashboard application. I am constantly needing to replace the sections of widgets so I use multiple named outlets. I've restructured your code so that the application template renders the index template into its single unnamed outlet.
Keys to this approach:
App.IndexRoute = Ember.Route.extend({
model: function(){
return Ember.RSVP.hash({
left: ['left one', 'left two'],
right: ['right one', 'right two']
});
},
renderTemplate: function(controller, model){
this.render();
this.render('left', {outlet: 'left', into: 'index', controller: 'left', model: model.left});
this.render('right', {outlet: 'right', into: 'index', controller: 'right', model: model.right});
}
});
Whenever you need to return multiple models, and you want your route to block until all models are returned, use Ember.RSVP.hash. You return multiple promises, each as properties of your returned model. RenderTemplate takes two parameters, controller and model so you access your model in the renderTemplate to manually pass the model into the controller of the template you are rendering.
As a slight alternative to this approach, if you need to render multiple datasources on the page, but you do not ever need to dynamically replace the whole template backing one of the models (ie render once and done), you can use the {{render}} helper.
<script type="text/x-handlebars" data-template-name="index">
<p>Index Template</p>
{{render 'left' model.left}}
{{render 'right' model.right}}
</script>
The benefit of this code is that our route has simplified.
App.IndexRoute = Ember.Route.extend({
model: function(){
return Ember.RSVP.hash({
left: ['left one', 'left two'],
right: ['right one', 'right two']
});
}
});
But, we have lost the ability to easily render something else here via action since we no longer have named outlets.

Ember.js: Loop over data from ArrayController in unassociated View

I have a route set up which pulls Account information from a REST endpoint:
Social.Router.map(function() {
this.resource('accounts');
});
Social.AccountsRoute = Ember.Route.extend({
model: function() {
return Social.Account.find();
}
});
Social.Account = DS.Model.extend({
name: DS.attr('string'),
username: DS.attr('string')
});
Social.AccountsController = Ember.ArrayController.extend();
I can loop over that data in my template like so:
<script type="text/x-handlebars" data-template-name="accountItem">
{{#each account in controller}}
<div class="avatar-name">
<p>{{account.name}}</p>
<p>{{account.username}}</p>
</div>
{{/each}}
</script>
I have another template in which I'd like to use the same account data. How would I retrieve the information associated with the Account model from within a View so that I can make it available in the corresponding template?
Social.NewPostView = Ember.View.extend({
tagName: 'div',
accounts: function(){
// return Account data here?
}
});
Update 1
Here's a quick view of my UI
On the left is "live" account data. On the right is static HTML. I'd like to reuse the data from the left on the right. Make sense?
You should take a look to the needs property for controllers. This allow you to specify a list of controllers you will be able to access from the current one.
More information on the emberjs guides
NewPostController
Social.NewPostController = Ember.ObjectController.extend({
needs: ['accounts'],
init: function(){
this._super();
console.log(this.get('controllers.accounts'))
}
});
Then, from your template:
<script type="text/x-handlebars" data-template-name="newPost">
{{#each account in controller.controllers.accounts}}
<div class="avatar-name">
<p>{{account.name}}</p>
<p>{{account.username}}</p>
</div>
{{/each}}
</script>

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!

Emberjs Application Routes and Controllers

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/).