CollectionView error in current ember-latest? - ember.js

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/

Related

Ember - partial template with fixture data

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>

The bound view does not update upon saving when using ember-model RESTAdapter.

I am exploring using ember-model (https://github.com/ebryn/ember-model), as an alternative to ember-data in my ember.js application. I don't have enough rep yet to create a new tag, but if so, I'd create ember-model.js to avoid confusion.
The desired behavior is to display a simple list of records and display a form to create new records via a RESTful rails API, Using GET and POST.
This worked smoothly with the Fixture Adaptor inside ember-model. Upon creation, as expected, the new record is pushed onto the Fixture array and the browser automatically updates to reflect the new record.
Using the ReST Adaptor, I was able to display the list and create a new record. However, the newly created record, which is bound to a template, will not update unless I hit the refresh button on the browser. And now I wonder what I might be doing wrong.
I dug around StackOverflow and elsewhere before I posted. I'm going to dig into the source next, but I thought I'd ask to see if anyone else has any insights.
Thank you, good people of Stack Overflow.
This is my app.js:
window.Dash = Ember.Application.create({
LOG_TRANSITIONS: true
});
Dash.Router.map(function() {
// put your routes here
this.resource('apps', function() {
this.route('add');
this.resource('app', { path: ':app_id' });
});
});
Dash.IndexRoute = Ember.Route.extend({
//temporary redirect to games list
redirect: function () {
this.transitionTo('apps');
}
});
Dash.AppsRoute = Ember.Route.extend({
model: function() {
return Dash.App.find();
}
});
Dash.AppsAddController = Ember.Controller.extend({
save: function() {
var name = this.get('name');
var id = this.get('id');
var account_id = this.get('account_id');
var auth_id = this.get('auth_id');
var state = Dash.AppState.selectedState;
var store_type = Dash.AppPlatform.selectedPlatform;
var store_app_id = this.get('store_app_id');
var download_url = this.get('download_url');
var newApp = Dash.App.create({
name: name,
id: id,
auth_id: auth_id,
state: state,
store_type: store_type,
store_app_id: store_app_id,
download_url: download_url
});
newApp.save();
}
});
Dash.AppPlatform = Ember.ArrayController.create({
selectedPlatform: null,
content: [
Ember.Object.create({id: 'itunes', name: 'iOS'}),
Ember.Object.create({id: 'android', name: 'Google Play'}),
Ember.Object.create({id: 'amazon', name: 'Amazon Appstore'}),
]
});
Dash.AppState = Ember.ArrayController.create({
selectedState: null,
content: [
Ember.Object.create({name: 'test'}),
Ember.Object.create({name: 'production'})
]
})
Dash.App = Ember.Model.extend({
id: Ember.attr(),
name: Ember.attr(),
auth_id: Ember.attr(),
state: Ember.attr(),
store_type: Ember.attr(),
store_app_id: Ember.attr(),
download_url: Ember.attr(),
});
Dash.App.adapter = Ember.RESTAdapter.create();
//hardcoding account id for now
Dash.App.url = 'http://localhost:3000/accounts/980190962/apps';
Dash.App.collectionKey = 'apps';
This is index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Dashboard</title>
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<h2>Dashboard</h2>
<script type="text/x-handlebars" data-template-name="application">
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="apps">
{{#linkTo 'apps.add' }}Add an App{{/linkTo}}
<h3>Apps List</h3>
{{#if model}}
<ol>
{{#each model}}
<li>{{#linkTo 'app' this}}{{name}}{{/linkTo}}</li>
{{/each}}
</ol>
<div>{{outlet}}</div>
{{else}}
<p>You have no Apps.</p>
{{/if}}
</script>
<script type="text/x-handlebars" data-template-name="apps/index">
<p>Click a game to Edit or click Add to enter a new App.</p>
</script>
<script type="text/x-handlebars" data-template-name="app">
<div>
Name: {{name}}<br />
ID: {{id}}<br />
Account ID: {{account_id}}<br />
AuthID : {{auth_id}}<br />
Test Mode?: {{state}}<br />
Store Type: {{store_type}}<br />
Store App ID: {{store_app_id}}<br />
Download URL: {{download_url}}
</div>
</script>
<script type="text/x-handlebars" data-template-name="apps/add">
<p><label for="name">Name:</label><br />{{view Ember.TextField valueBinding='name'}}</p>
<p><label for="id">ID:</label><br />{{view Ember.TextField valueBinding='id'}}</p>
<p><label for="account_id">Account ID:</label><br />{{view Ember.TextField valueBinding='account_id'}}</p>
<p><label for="auth_id">Auth ID:</label><br />{{view Ember.TextField valueBinding='auth_id'}}</p>
<p><label for="state">Test Mode:</label><br />{{view Ember.Select contentBinding='Dash.AppState' valueBinding='Dash.AppState.selectedState' optionValuePath="content.name" optionLabelPath="content.name"}}</p>
<p><label for="store_type">Store Type:</label><br />{{view Ember.Select contentBinding='Dash.AppPlatform' valueBinding='Dash.AppPlatform.selectedPlatform' optionValuePath="content.id" optionLabelPath="content.name"}}</p>
<p><label for="store_app_id">Store App ID:</label><br />{{view Ember.TextField valueBinding='store_app_id'}}</p>
<p><label for="download_url">Download URL:</label><br />{{view Ember.TextField valueBinding='download_url'}}</p>
<p><button {{action 'save'}}>Save</button></p>
</script>
<script src="js/libs/jquery-1.9.1.js"></script>
<script src="js/libs/handlebars-1.0.0-rc.4.js"></script>
<script src="js/libs/ember-1.0.0-rc.6.js"></script>
<script src="js/libs/ember-model.js"></script>
<script src="js/app.js"></script>
</body>
</html>
It won't automatically work this way. Your content array in the AppState controller is just a static array with items in it. You'd have to do something like this
this.controllerFor('Apps').get('content').pushObject(newApp) to see it reflect in the UI.
Your Apps controller will be an ArrayController because the Apps route's model function returned an array.

Ember.js template rendering

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.

very Basic ember router example unsolved

I tried this very basic ember router example following the ember-router-example. But when I run it, it shows me an empty page. I checked the console window for any errors, but seems to be fine. Not really sure why this is not working and where am missing.
I am just trying to create the first level links of Home, Sections, items only.
Can somebody help me?
index.html:
<body>
<script src="js/libs/jquery-1.7.1.js"></script>
<script src="js/libs/jquery.lorem.js"></script>
<script src="js/libs/bootstrap.min.js"></script>
<script src="js/libs/handlebars-1.0.0.beta.6.js"></script>
<script src="js/libs/ember.js"></script>
<script src="js/app.js"></script>
<script type="text/x-handlebars" data-template-name="application">
<div>
<ul>
<li><a {{action "doHome"}}>Home</a></li>
<li><a {{action "doSections"}}>Sections</a></li>
<li><a {{action "doItems"}}>Items</a></li>
</ul>
</div>
<div>
{{outlets}}
</div>
</script>
<script type="text/x-handlebars" data-template-name="home">
<h1>yeah right Home</h1>
</script>
<script type="text/x-handlebars" data-template-name="sections">
<h1>Oh v in Sections index</h1>
</script>
<script type="text/x-handlebars" data-template-name="items">
<h1>correct in Items Index Page</h1>
</script>
</body>
app.js :
$(function() {
App = Ember.Application.create()
App.ApplicationController = Ember.Controller.extend();
App.ApplicationView = Ember.View.extend({
templateName:'application'
});
App.HomeController = Ember.Controller.extend();
App.HomeView = Ember.View.extend({
templateName:'home'
});
App.SectionsController = Ember.Controller.extend();
App.SectionsView = Ember.View.extend({
templateName:'sections'
});
App.ItemsController = Ember.Controller.extend();
App.ItemsView = Ember.View.extend({
templateName:'items'
});
App.Route = Ember.Route.extend({
root: Ember.Route.extend({
doHome : function(router,event){
router.transitionTo('home');
},
doSections:function(router,event){
router.transitionTo('sections');
},
doitems:function(router,event){
router.transitionTo('items');
},
home : Ember.Route.extend({
route : '/',
connectOutlets:function(router,event){
router.get('applicationController').connectOutlet('home');
}
}),
sections : Ember.Route.extend({
route : '/sections',
connectOutlets:function(router,event){
router.get('applicationController').connectOutlet('sections');
}
}),
items : Ember.Route.extend({
route : '/items',
connectOutlets:function(router,event){
router.get('applicationController').connectOutlet('items');
}
})
})//root
}) //router
});
I created this fiddle with your code. It seems to be working, just use latest ember and handlebars. And maybe you should change {{outlets}} with {{outlet}}.
EDIT
The above fiddle is not working, see the updated fiddle.
I rewrote the routing code using the new routing API, now it is working as expected.
I believe you are supposed to be using "template" as opposed to templateName when you are defining your templates in your main html file. If you were to create those templates as separate handlebars files and use a build step, you would then use templateName to refer to them (by file name).
Steve

ember.js statemanager use for tabs

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.