I just started with Ember and have a basic web app structure in place. I have a partial template set up and want to bring some test data into it. I can see my test data if I use my 'home' template for it, but I can not get it into my collections partial template. I'm almost certain it has to be related to basic Ember concepts that I have no familiarity with. Here is my simplified html and below is the Ember js. If anybody has any idea how I could bring the 'each' loop from 'home' template into my partial 'collections' template, I'll be very thankful:
[code]
<script type="text/x-handlebars" ><!-- data-template-name="application" -->
<div id="main">
<ul>
<li>
<image src="logo.png" style="width:439px;height:102px;"/>
</li>
<li>{{#link-to 'home'}}Home{{/link-to}} | {{#link-to 'help'}}Help{{/link-to}}</li>
</ul>
</div>
<div class="collections">
{{partial 'collections'}}
</div>
<div class="statistics">
{{outlet}}
</div>
</script>
<script type="text/x-handlebars" id="collections">
COLLECTIONS<br/>
<!-- here is where I wand the 'each' loop to go -->
</script>
<script type="text/x-handlebars" id="home">
OnLoad : This is Home Page<br/>
<ul>
{{#each}}
<li>
<label>{{title}}</label>
</li>
{{/each}}
</ul>
</script>
<script type="text/x-handlebars" id="help">
Welcome to Help Page
</script>
[/code]
And here is JS code for the above:
[code]
App = Ember.Application.create();
App.Router.map(function(){
this.resource('home', { path: '/' });
this.resource('help');
});
App.CollectionsRoute = Ember.Route.extend({
model: function(){
return items;
}
});
App.HomeRoute = Ember.Route.extend({
model: function(){
return items;
}
});
var items = [
{
id: 1,
title: 'Item 1',
belongsTo: 'parent path 1'
},{
id: 2,
title: 'Item 2',
belongsTo: 'parent path 2'
},{
id: 3,
title: 'Item 3',
belongsTo: 'parent path 3'
}
];
[/code]
partial 'collections' have the same context of application template. So if you declare:
App.ApplicationRoute = Ember.Route.extend({
model: function(){
return items;
}
});
Will be able to use:
<script type="text/x-handlebars" id="collections">
COLLECTIONS<br/>
<ul>
{{#each}}
<li>
<label>{{title}}</label>
</li>
{{/each}}
</ul>
</script>
Related
I have an index route where I need to populate a menu in one outlet based on a list of models. However I cannot get the models to be represented in the each statement.
Here is the Category Model:
App.Category = DS.Model.extend({
title: DS.attr('string'),
parent: DS.belongsTo('App.Category')
})
And here is the indexRoute where I render it
App.IndexRoute = Em.Route.extend({
renderTemplate: function(){
this.render('index')
this.render('categoryMenu',
{
outlet: 'sidebar',
into: 'index',
model: function() {
return App.Category.find()
},
controller: App.CategoriesController
})
this.render('badgesList',{
outlet: 'badgesList',
into: 'index'
})
}
})
Index Template:
<script type="text/x-handlebars" data-template-name="index">
<div class="span3">
{{outlet sidebar}}
</div>
<div class="span8">
{{outlet badgesList}}
</div>
</script>
Nested Category Template
<script type="text/x-handlebars" data-template-name="categoryMenu">
<ul>
{{#each model}}
{{title}}
{{/each}}
</ul>
</script>
I have tried to change the each statement to several different things like controller or item in model but nothing is displayed.
Thank you for any help!
Make yourself CategoriesController first like this:
App.CategoriesController = Ember.ArrayController.extend({
content: function () {
return App.Category.find()
}.property()
});
rename your template just to categories
<script type="text/x-handlebars" data-template-name="categories">
<ul>
{{#each model}}
{{title}}
{{/each}}
</ul>
</script>
in your index template replace {{outlet}} with {{render 'categoies'}}
<script type="text/x-handlebars" data-template-name="index">
<div class="span3">
{{render 'categoies'}}
</div>
<div class="span8">
{{outlet badgesList}}
</div>
</script>
as last thing remove the call rendering categoryMenu.
I'm possibly reading the docs wrong. Can someone please check out my gist and tell me why the invoices/index template is not rendering?
When I read the ember.js docs it states it should render
posts
↳posts/index
(invoices/index in my case). The invoices template renders however.
Handlebars:
<script type="text/x-handlebars" data-template-name="application">
<h1>Ember Committers</h1>
<nav>
{{#linkTo "index"}}Index{{/linkTo}}
{{#linkTo "about"}}About{{/linkTo}}
{{#linkTo "invoices"}}Invoices{{/linkTo}}
</nav>
{{ outlet }}
</script>
<script type="text/x-handlebars" data-template-name="invoices">
<h1>Invoices</h1>
</script>
<script type="text/x-handlebars" data-template-name="invoices/index">
<ul>
{{#each invoice in invoices }}
<li>{{#linkTo "show" invoice.id}}{{ invoice.id }}{{/linkTo }}</li>
{{/each }}
</ul>
</script>
<script type="text/x-handlebars" data-template-name="invoices/show">
<p>Invoice - {{ name }}</p>
</script>
<script type="text/x-handlebars" data-template-name="phone">
<p>Contributor - {{ title }}</p>
</script>
<script type="text/x-handlebars" data-template-name="about">
<p>About {{ title }}</p>
</script>
<script type="text/x-handlebars" data-template-name="index">
<p>Index</p>
</script>
JavaScript:
<script type="text/javascript" defer>
var App = Ember.Application.create({
LOG_TRANSITIONS: true
});
App.ApplicationView = Ember.View.extend({
templateName: 'application'
});
App.Router.map(function () {
this.route("about");
this.resource("invoices", { path: "/invoices" }, function () {
this.resource("show", { path: "/:id" });
});
});
var invoices = [
{id: 1},
{id: 2}
];
App.AboutRoute = Ember.Route.extend({
setupController: function (controller) {
// Set the IndexController's `title`
controller.set('title', "My App");
}
});
App.InvoicesIndexController = Ember.ArrayController.extend({
invoices: invoices
});
</script>
You need to include an {{outlet}} tag in your invoices template. Since index and show are nested resources of invoices, their templates get rendered inside the outlet that you specify in the invoices template.
Take a look at the nested resources part of the Ember.js guide.
I am working with EmberJs and can't figure out why the following code won't render the 'new' template. When I navigate to /shops, I get a list of shops and a create button linking to '/shops/new', but when I click create, the 'new' template isn't rendered and instead stays the same as 'shops'. I can navigate to each individual shop fine, just not new.
App.js
window.App = Ember.Application.create();
App.Router.reopen({
location: 'history'
});
// Router
App.Router.map(function() {
this.resource('shops', function() {
this.route('new');
});
this.resource('shop', { path: '/shops/:shop_id' });
});
App.ShopsRoute = Ember.Route.extend({
model: function() {
return App.Shop.find();
}
});
App.ShopsNewRoute = App.ShopsRoute.extend({
model: function() {
return App.Shop.createRecord();
},
setupController: function( controller, model ) {
return this._super(),
controller.set( 'content', model )
}
});
App.ShopsNewController = Ember.ObjectController.extend();
// Models
App.Store = DS.Store.extend({
revision: 11,
adapter: DS.RESTAdapter
});
App.Shop = DS.Model.extend({
name: DS.attr('string'),
body: DS.attr('string'),
});
Index.html
<!DOCTYPE html>
<html>
<head>
<title>Ember/Rails App</title>
<%= stylesheet_link_tag "application", :media => "all" %>
<%= javascript_include_tag "application" %>
<%= csrf_meta_tags %>
</head>
<body>
<script type="text/x-handlebars" data-template-name="application">
<div class="row">
<div class="twelve columns">
<h1>Ordr</h1>
<hr>
{{outlet}}
</div>
</div>
</script>
<script type="text/x-handlebars" data-template-name="shops/new">
<h2>New Shop</h2>
</script>
<script type="text/x-handlebars" data-template-name="shops">
{{#each shop in controller}}
{{#linkTo "shop" shop}} {{ shop.id }}{{/linkTo}}
{{/each}}
{{#linkTo 'shops.new'}}Create{{/linkTo}}
</script>
<script type="text/x-handlebars" data-template-name="shop">
<h2>{{name}}</h2>
<p>{{body}}</p>
</script>
</body>
</html>
The way you have set up your routes and templates, you are telling Ember that you want to navigate to shops.new and keep all the list of shops showing even while you are in shops.new.
If that is in fact the scenario that you want, all you need to do is add an {{outlet}} inside the shops template:
<script type="text/x-handlebars" data-template-name="shops">
{{#each shop in controller}}
{{#linkTo "shop" shop}} {{ shop.id }}{{/linkTo}}
{{/each}}
{{#linkTo 'shops.new'}}Create{{/linkTo}}
{{outlet}}
</script>
However, if that is not what you really intend, and you actually want the list of shops to be hidden when you transition to shops.new, then you will need to change a couple of things.
change your App.ShopsRoute to App.ShopsIndexRoute :
App.ShopsIndexRoute = Ember.Route.extend({
model: function() {
return this.store.find('shop');
}
});
and your shops template to shops/index template:
<script type="text/x-handlebars" data-template-name="shops/index">
{{#each shop in controller}}
{{#linkTo "shop" shop}} {{ shop.id }}{{/linkTo}}
{{/each}}
{{#linkTo 'shops.new'}}Create{{/linkTo}}
</script>
Any of those 2 methods should fix your problem, depending on what your intentions are.
I made some tests with ember-0.9.8.1.js and the following code works as expected.
After that I read about the router and that the router - code is only available in the current ember-latest.js (16.06.2012).
I test the code below with this version.
The problem is the list is rendered:
<div id="ember143" class="ember-view">
<ul id="PersonList" class="ember-view ListBox">
<li id="ember179" class="ember-view">
<script id="metamorph-0-start" type="text/x-placeholder"></script>
<script id="metamorph-0-end" type="text/x-placeholder"></script>
</li>
<li id="ember183" class="ember-view">
<script id="metamorph-1-start" type="text/x-placeholder"></script>
<script id="metamorph-1-end" type="text/x-placeholder"></script>
</li>
<li id="ember187" class="ember-view">
<script id="metamorph-2-start" type="text/x-placeholder"></script>
<script id="metamorph-2-end" type="text/x-placeholder"></script>
</li>
<li id="ember191" class="ember-view">
<script id="metamorph-3-start" type="text/x-placeholder"></script>
<script id="metamorph-3-end" type="text/x-placeholder"></script>
</li>
</ul>
</div>
but is empty.
Something with the
template: Ember.Handlebars.compile("{{content.name}}"),
is not working correctly or some syntax aspects has changed.
The code line
console.log("content:",this.get('content'));
in the click handler shows, that the right content is there, but
Ember.Handlebars.compile("{{content.name}}"),
will not render the content.
Is this a bug ???
Javascript Code:
var App = Em.Application.create({
ready: function(){
App.personListController.getData();
}
});
// Model Objects
App.Person = Ember.Object.extend({
name: null,
myTickets: null,
selected: false
});
// Liste von Personen anlegen
App.personListController = Ember.ArrayController.create({
getData: function(){
$.get('json/person.json', function(data) {
var personList = Ember.A([]);
data.forEach(function(item) {
var p = App.Person.create({
'name': item.name,
'myTickets': null,
'selected': false
});
personList.pushObject(p);
});
App.personListController.set('content', personList);
})
},
resetSelection: function(){
App.personListController.content.forEach(function(item){
item.set('selected',false);
})
},
selectedPerson: null
});
App.PersonList = Ember.CollectionView.extend({
tagName: 'ul',
contentBinding: 'App.personListController.content',
classNames: ['ListBox'],
mouseenter: function(event){
console.log("PersonList.content:",this.get('content'));
},
itemViewClass: Ember.View.extend({
template: Ember.Handlebars.compile("{{content.name}}"),
classNameBindings: ['selected:selected'],
selectedBinding: 'content.selected',
click:
function(event){
App.personListController.resetSelection() ;
this.setPath('content.selected',true);
App.personListController.set('selectedPerson',this.get('content'));
console.log("ItemViewInfo selected:",this.getPath('content.selected'));
console.log("content:",this.get('content'));
//this.set('isSelected',true);
}
})
});
HTML:
<script type="text/x-handlebars">
{{#view App.PersonList id="PersonList"}}
{{/view}}
</script>
That's because the lookup context for a view changed in the latest commits. Now you have to prepend view if you want to lookup a property on the view. See documentation updates in commit 8a6c6.
The template therefore changes to
template: Ember.Handlebars.compile("{{view.content.name}}")
see http://jsfiddle.net/pangratz666/DsdHU/.
Tom Dale has a Gist which explains the changes further.
The latest-ember.js (aswell as ember-1.0.pre.js) does not include handlebars anymore, you have to include it by your own.
You also have to start the event-loop yourself now:
!! -> seems like you don't need that anymore.. !!
App.initialize();
..the associated jsfiddle: http://jsfiddle.net/aGMzD/
i have 3 tabs navigation and the content of each tab is different obviously.
i'm thinking about using StateManager in Emberjs to manager my tab views.
http://docs.emberjs.com/#doc=Ember.StateManager&src=false
is that a good idea? or is there a better router out there? i've looked at
sproutcore-routing
ember-routemanager
are those better than the statemanager? what's the reason not to use statemanager?
You can use something along this lines, see http://jsfiddle.net/pangratz666/e3wM7/:
Handlebars:
<script type="text/x-handlebars" >
<ul>
<li {{action "showFirst" target="App.stateManager"}} >First tab</li>
<li {{action "showSecond" target="App.stateManager"}} >Second tab</li>
</ul>
<div class="tab-content" ></div>
</script>
<script type="text/x-handlebars" data-template-name="first" >
first
</script>
<script type="text/x-handlebars" data-template-name="second" >
second
</script>
JavaScript:
App.stateManager = Ember.StateManager.create({
rootElement: '.tab-content',
initialState: 'firstTab',
showFirst: function(manager) {
manager.goToState('firstTab');
},
showSecond: function(manager) {
manager.goToState('secondTab');
},
firstTab: Ember.ViewState.create({
view: Ember.View.extend({ templateName: 'first' })
}),
secondTab: Ember.ViewState.create({
view: Ember.View.extend({ templateName: 'second' })
})
});
Also take a look at the blog post Anatomy of an Ember.js App Part I Redux: Routing and Outlets.