rendering a template with multiple outlets - ember.js

I was trying to render out some content n the named outlets with no success. I tried following How to render multiple templates for a route in Router v2 but the solution there is not working for me!
My html page looks like:`
<!DOCTYPE html>
<head>
<meta charset="utf-8" />
<!-- Set the viewport width to device width for mobile -->
<meta name="viewport" content="width=device-width" />
<title>Demo</title>
<style>
.main-container{
width:800px;
margin:0px auto;
}
</style>
</head>
<body>
<script type="text/x-handlebars" data-template-name="application">
<div class="main-container">
<div>{{outlet topMenu}}</div>
<div>
<div style="float:left; width:30%;">{{outlet sideMenu}}</div>
<div style="float:left; width:70%;">{{outlet content}}</div>
</div>
</div>
</script>
<script type="text/x-handlebars" data-template-name="menu">
<ul>
{{#each model}}
<li>{{label}}</li>
{{/each}}
</ul>
</script>
<script src="../js/ember/libs/jquery-1.9.1.js"></script>
<script src="../js/ember/libs/handlebars-1.0.0-rc.4.js"></script>
<script src="../js/ember/libs/ember-1.0.0-rc.6.1.js"></script>
<script src="../js/ember/libs/ember-data-master.js"></script>
<script src="../js/ember/demo.js"></script>
</body>
</html>
At the moment I don't even want to bother about the sideMenu and content, I just wanted to get the top menu showing up to start with.The corresponding js is:
window.App = Ember.Application.create();
// Router
App.Router.map(function() {
this.resource('menu',{ path: "/" },function(){
this.resource('sideMenu',{ path: "/:menu_id" },function(){
this.resource('content',{path:'/content/:content_id'});
});
});
});
App.IndexRoute = Ember.Route.extend({
renderTemplate: function() {
this.render('menu',{outlet:'topMenu',controller:this.controllerFor('menu', App.Menu.find())});
}
});
App.MenuRoute = Ember.Route.extend({
model:function(){
return App.Menu.find();
}
});
App.Store = DS.Store.extend({
revision:12,
adapter:'DS.FixtureAdapter'
//adapter:DS.RESTAdapter.extend({
// url: 'http://....'
//})
});
App.Menu = DS.Model.extend({
label: DS.attr('string')
,subMenu: DS.hasMany('App.subMenu')
});
App.SubMenu = DS.Model.extend({
label: DS.attr('string')
,content :DS.attr('string')
});
App.SubMenu.FIXTURES = [
{
id:1
,label:"Sub1"
,content:'Hello there 1'
}
,{
id:2
,label:"Sub2"
,content:'Hello there 2'
},{
id:3
,label:"Sub3"
,content:'Hello there 3'
},{
id:4
,label:"Sub4"
,content:'Hello there 4'
}
];
App.Menu.FIXTURES = [
{
id:1,
label:"Home",
subMenu:[1,2]
},
{
id:2,
label:"Api",
subMenu:[3,4]
}
];`
I am not sure if my router is set up in-correctly. Any feedback would be highly appreciated.
Regards,
Dee

I'm guessing that IndexRoute is not being used by ember. Probably what you want instead is to use MenuIndex:
App.MenuIndexRoute = Ember.Route.extend({
renderTemplate: function() {
this.render('menu',{outlet:'topMenu',controller:this.controllerFor('menu', App.Menu.find())});
}
});
Try turning on logging so that you can see which routes/controllers/views/templates are being used by ember:
var App = Ember.Application.create({
LOG_VIEW_LOOKUPS: true,
LOG_ACTIVE_GENERATION: true
});
http://blog.emberwatch.com/2013/06/13/logging-the-magic-in-ember-js.html

Related

Ember - Nothing handled the action occurs

Nothing handled the action error occurs for the following code. How to resolve this?
I have created a view, an object for my sample app using ember. But the action part is not working.
How to bind an action to a view?
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Ember Starter Kit</title>
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/style.css">
<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.no-icons.min.css" rel="stylesheet">
</head>
<body>
<script type="text/x-handlebars">
<ul class="mod-choosable-list">
{{view Ember.CollectionView
contentBinding="App.teachersController"
itemViewClass="App.TeacherView"
tagName="div"
}}
</ul>
</script>
<script type="text/x-handlebars" data-template-name="teacher-view">
<div {{action 'refresh'}}><b>{{view.content.name}}</b></div>
</script>
<script src="js/libs/jquery-v1.11.1.js"></script>
<script src="js/libs/handlebars-v1.3.0.js"></script>
<script src="js/libs/ember-v1.6.1.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/showdown/0.3.1/showdown.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/moment.js/2.1.0/moment.min.js"></script>
<script src="js/app.js"></script>
</body>
</html>
JS:
App = Ember.Application.create({});
App.Teacher = Ember.ObjectController.extend({
id: null,
name: null,
students: null,
actions: {
refresh: function(){
alert("refresh");
}
}
});
App.TeacherView = Ember.View.extend({
templateName: 'teacher-view'
});
App.set('teachersController', Ember.ArrayController.create({
content: [
App.Teacher.create({id:1, name: "mr.katz", students: [2, 3]}),
App.Teacher.create({id:2, name: "mr.dale", students: [1]})
]
}));
When you trigger the action refresh, ember will look for the action in the controller. Since you have not specified a controller for the view, the controller for the application template will be used which is App.ApplicationController.
You can use the following code and your action will trigger.
App.ApplicationController = Em.Controller.extend({
actions: {
refresh: function(){
alert("refresh");
}
}
});
You can specify the actions in the view too. In that case you will need to specify the target for the action. This will tell ember where to look for the action handler.
App.TeacherView = Ember.View.extend({
templateName: 'teacher-view',
actions: {
refresh: function(){
alert("refresh");
}
}
});
<div {{action 'refresh' target="view"}}><b>{{view.content.name}}</b></div>
You can specify a controller for view on its init event.
App.TeacherView = Ember.View.extend({
templateName: 'teacher-view',
setup:function() {
this.set('controller', App.Teacher.create());
}.on('init')
});

ember doesn't access to websocketAdapter

I'm new with ember and i'm trying to do a websocket that receives JSON data from my golang Server in real time , The problem with my code is that it doesn't seem to be reading the adapter that i have created and so my socket doesn't connect to the server. I think that my code is missing something in application.js or index.html that will allow me to access to my adapter and use its methods!
this is my application.js:
App = Ember.Application.create({
LOG_TRANSITIONS: true
})
/******************************* Post Template **************************************/
//Define a route for the template "post"
App.Router.map(function() {
this.route("post", { path: "/post" });
});
App.PostsRoute = Ember.Route.extend({
model: function() {
return this.store.find("posts");
console.log(post);
}
})
//Post Model
App.Post = DS.Model.extend({
name: DS.attr('string'),
number: DS.attr('string')
});
/**************************** websocket mixin ************************************/
App.WebSocketHandler = Ember.Object.extend({
uri: 'ws://localhost:8081/',
//ws: undefined
initialize: function() {
// this.ws = new WebSocket(this.uri);
var ws = new WebSocket(uri);
// callbacks
this.ws.onopen = function() {
console.log('Connection established /all');
};
this.ws.onclone = function() {
console.log('Connection closed /' + 'all');
};
this.ws.onmessage = function(data) {
DS.get('defaultStore').load(App.Post, data); //Simply load your json in the store.
};
this._super();
}
});
/************************* websocket Adapter ********************************************/
DS.SocketAdapter = DS.RESTAdapter.extend({
socket: undefined,
init: function(){
this.socket = new App.WebSocketHandler();
this._super();
},
find: function (store, type, id) {
// empty block
console.log('find');
},
findAll: function (store, type) {
// empty block
console.log('findAll');
},
createRecord: function(store, type, record) {
// code not relevant
console.log('createRecord');
}
});
App.ApplicationAdapter = DS.SocketAdapter;
// Use the adapter in the store
App.Store = DS.Store.extend({
revision: 12,
adapter: 'SocketAdapter'
});
and my index.html:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<title>Ember.js Example Application</title>
<script src="js/libs/jquery-1.10.2.js"></script>
<script src="js/libs/handlebars-1.1.2.js"></script>
<script src="js/libs/ember-1.5.1.js"></script>
<script src="js/libs/Ember_Data.js"></script>
<script src="js/application.js"></script>
<script src="js/router.js"></script>
<script src="js/models/model.js"></script>
</head>
<body>
<h1>Bonjour </h1>
<script type="text/x-handlebars">
Hello, {{firstName}} {{lastName}}<br/>
<nav>
{{#link-to 'post'}}Post{{/link-to}}
</nav>
<div>
{{outlet}}
</div>
</script>
<script type="text/x-handlebars" data-template-name="index">
<h2>My Wrappers</h2>
<ul>
{{#each post in model}}
<li>{{post.number}}</li>
{{/each}}
</ul>
</script></p>
<script type="text/x-handlebars" data-template-name="post">
<ul>
{{#each post in model}}
<li>Wrapper Name: {{post.name}}</li>
<li>Wrapper Number: {{post.number}}</li>
{{/each}}
</ul>
</script>
<script type="text/javascript">
</script>
</head>
<body>
</body>
</html>
You have some errors in your code.
1) Ember Object uses its own create method.
this.socket = new App.WebSocketHandler();
// change to
this.socket = App.WebSocketHandler.create({});
2) Your route and route template was not correctly named to posts.
this.route("posts", { path: "/posts" });
http://emberjs.jsbin.com/qixur/1/edit

Parse Ember fixture data and make available to nested view

I am trying to feed fixture data to both a handlebars template and a nested view. With my current setup, the data reaches my handlebars template just fine, but not the view. I suspect I am missing some basic piece of the ember.js puzzle. Would someone please advise me?
I've asked a question about a setup that is similar but uses ajax instead of fixture data, but have further simplified my setup in the hopes of getting some direction.
Thank you!
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Ember Starter Kit</title>
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/leaflet.css">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<script type="text/x-handlebars">
{{outlet}}
</script>
<script type="text/x-handlebars" id="index">
{{view App.MapView id="map" contentBinding="this"}}
<div id="blog">
<ul>
{{#each}}
<li>{{title}}</li>
{{/each}}
</ul>
</div>
</script>
<script src="js/libs/jquery-1.10.2.js"></script>
<script src="js/libs/handlebars-1.1.2.js"></script>
<script src="js/libs/ember-1.5.0.js"></script>
<script src="js/libs/ember-data.js"></script>
<script src="js/libs/leaflet-src.js"></script>
<script src="js/app.js"></script>
</body>
</html>
window.App = Ember.Application.create();
App.ApplicationAdapter = DS.FixtureAdapter.extend();
App.Router.map(function() {
this.resource('index', { path: '/' });
});
App.IndexRoute = Ember.Route.extend({
model: function () {
return this.store.find('storyPrev');
}
});
App.StoryPrev = DS.Model.extend({
title: DS.attr('string')
});
App.StoryPrev.FIXTURES = [
{
id: 1,
title: 'You Better Believe This!',
coordinates: [-73.989321, 40.6778]
},
{
id: 2,
title: 'Holy Crap, Unreal!',
coordinates: [-73.989321, 40.6779]
},
{
id: 3,
title: 'Big Bucks Made E-Z!',
coordinates: [-73.989321, 40.6780]
}
];
App.MapView = Ember.View.extend({
didInsertElement: function () {
var map = L.map('map', {zoomControl: false}).setView([40.685259, -73.977664], 14);
L.tileLayer('http://{s}.tile.cloudmade.com/[redacted key]/[redacted id]/256/{z}/{x}/{y}.png').addTo(map);
L.marker([40.685259, -73.977664]).addTo(map);
console.log(this.get('content'));
//THIS IS WHERE I GET STUCK
}
});
The view is backed by a controller, so you would do this.get('controller') to get the controller which is backed by your collection which if you wanted to get the collection (which isn't necessary since you can iterate the controller) you could do this.get('controller.model').
var controller = this.get('controller');
controller.forEach(function(item){
console.log(item.get('title'));
});
http://emberjs.jsbin.com/OxIDiVU/373/edit

How to render hasMany relationship data?

How can I get the following example code to render not just the person data but also the phone numbers of that person when rendering the URL /#/persons/1. I try to loop though the phone numbers with {{#each phoneNumber in phoneNumbers}} but there has to be a fundamental understanding error on my side.
Right now I only get:
app.js
App = Ember.Application.create({
LOG_TRANSITIONS: true,
rootElement: '#container'
});
// Router
App.Router.map(function() {
this.resource('persons', function() {
this.resource('person', { path: ':person_id' });
});
this.resource('phoneNumbers', function() {
this.resource('phoneNumber', { path: ':phone_number_id' });
});
});
App.PersonsRoute = Ember.Route.extend({
model: function() {
return App.Person.find();
}
});
App.PhoneNumbersRoute = Ember.Route.extend({
model: function() {
return App.PhoneNumber.find();
}
});
// Models
App.Store = DS.Store.extend({
revision: 11,
adapter: 'DS.FixtureAdapter'
});
App.Person = DS.Model.extend({
firstName: DS.attr('string'),
lastName: DS.attr('string'),
phoneNumbers: DS.hasMany('App.PhoneNumber')
});
App.PhoneNumber = DS.Model.extend({
number: DS.attr('string'),
person: DS.belongsTo('App.Person')
});
App.Person.FIXTURES = [{
id: 1,
firstName: 'X',
lastName: 'Smith'
}, {
id: 2,
firstName: 'Y',
lastName: 'Smith'
}];
App.PhoneNumber.FIXTURES = [{
id: 1,
person_id: 1,
number: '20'
}, {
id: 2,
person_id: 1,
number: '23'
}, {
id: 3,
person_id: 2,
number: '42'
}];
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Phone book</title>
</head>
<body>
<div id='container'></div>
<script type="text/x-handlebars" data-template-name="application">
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="persons">
<p>All people:</p>
<ul>
{{#each controller}}
<li>{{firstName}} {{lastName}}</li>
{{/each}}
</ul>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="person">
<h1>{{firstName}} {{lastName}}</h1>
{{#if phoneNumbers.length}}
<ul>
{{#each phoneNumber in phoneNumbers}}
<li>{{phoneNumber.number}}</li>
{{/each}}
</ul>
{{/if}}
</script>
<script type="text/x-handlebars" data-template-name="phone_numbers">
<ul>
{{#each controller}}
<li>{{number}}</li>
{{/each}}
</ul>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="phone_number">
<h1>{{number}}</h1>
</script>
</body>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src="js/handlebars.js"></script>
<script type="text/javascript" src="js/ember.js"></script>
<script type="text/javascript" src="js/ember-data.js"></script>
<script type="text/javascript" src="js/app.js"></script>
</html>
Ember-data doesn't act like ActiveRecord in this regard: when you use has_many you have to have a property that is an array of ids for the records. It isn't enough to have a foreign key for the owner on the reciprocal model.
try adding phoneNumbers: [1, 2] to your first Person fixture, and phoneNumbers: [3] to the second.
If you were using the RESTAdapter, those key names would be phone_number_ids instead. If you use active_model_serializers you can use the embed feature to automatically include an array of ids.

CollectionView error in current ember-latest?

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/