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.
Related
Taking the following as an example:
<script type="text/x-handlebars">
<h2>Welcome to Ember.js</h2>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="index">
<ul>
{{#each model as |item|}}
<li>{{item}}</li>
{{/each}}
{{magnus-component name=firstName}}
</ul>
</script>
<script type="text/x-handlebars" data-template-name="components/magnus-component">
<!-- Doesn't appear -->
{{name}}
</script>
...and
App = Ember.Application.create();
App.Router.map(function() {
});
App.IndexRoute = Ember.Route.extend({
model: function() {
return ['red', 'yellow', 'blue'];
},
name: "Magnus",
surname: "Womble",
fullName: Ember.computed('name', 'surname', function(){
return this.get('name') + ' '+this.get('surname');
})
});
Which can be found in the following jsbin:
http://emberjs.jsbin.com/higako/edit?html,js,output
How do you correctly pass the fullName property to the component template?
You should move your logic from IndexRoute to IndexController:
App.IndexController = Ember.Controller.extend({
name: "Magnus",
surname: "Womble",
fullName: Ember.computed('name', 'surname', function(){
return this.get('name') + ' '+this.get('surname');
})
});
And then, if you use:
{{magnus-component name=fullName}}
instead of (firstName isn't defined anywhere):
{{magnus-component name=firstName}}
It will work.
Working demo.
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
EDIT: I found this very interesting question and answer here, but unfortunately it does not work with Ember 1.0. It would be great if someone could edit it for ember 1.0. The JsFiddle is here.
I want to articulate my app around (a) first language choice, then (b) a page choice, so I have the following routes
App.Router.map(function () {
this.resource('lang', { path: '/:lang_id' }, function() {
this.resource('page', { path: '/:page_id' });
});
});
Implemented by
App.ApplicationRoute = Em.Route.extend({
model: function() {
return this.store.find('lang');
}
});
App.LangIndexRoute = Em.Route.extend({
model: function(params) {
return this.store.find('lang', params.lang_id);
}
});
App.PageRoute = Em.Route.extend({
model: function(params) {
return this.store.find('page', params.page_id);
}
});
model is :
App.Lang = DS.Model.extend({
name: DS.attr('string'),
pages: DS.hasMany('page')
});
App.Page = DS.Model.extend({
lang: DS.belongsTo('lang'),
name: DS.attr('string'),
title: DS.attr('string'),
extra_title: DS.attr('string'),
});
App.Lang.FIXTURES = [
{
id: 'en',
name: 'EN',
pages: [1, 2]
},
{
id: 'fr',
name: 'FR',
pages: [3]
},
];
App.Page.FIXTURES = [
{
id: 'page-item1',
name: 'ITEM1',
title: 'ITEM1',
extra_title: 'item1',
},
{
id: 'page-item2',
name: 'ITEM2',
title: 'ITEM2',
extra_title: 'item2',
},
{
id: 'page-item3',
name: 'ITEM3',
title: 'ITEM3',
extra_title: 'item3',
},
];
And the following markup :
<script type="text/x-handlebars" >
<nav>
<ul>
{{#each}}
<li>{{#linkTo 'lang' this currentWhen="lang" activeClass="selected" }}{{name}}{{/linkTo}}</li>
{{/each}}
</ul>
</nav>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="lang/index">
<nav>
<ul class="projects">
{{#each pages}}
<li>{{#link-to "page" activeClass="selected"}}{{name}}{{/link-to}}</li>
{{else}}
<li>Loading...</li>
{{/each}}
</ul>
</nav>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="page">
</script>
I cannot get the pages listed for the given language to be enumerated when loading the lang.index template.
How could I do that, or would there be a better way to manage language with ember ?
I think my mistake (or misunderstanding of the framework) is either in the model hook or in the iterator of #each...
I unblock the situation by modifying the route, model and template as below.
One of the problem was due to the need of declaring the hasmany relationship as async. (using FIXTURES), the other were related to the linkTo in the template.
However I still don't have exactly the behavior I want in the pages/index template. All pages are rendered, instead of only the one of the given language.
App.Router.map(function () {
this.resource('pages', { path: '/:lang_id' }, function() {
this.route('page', { path: '/:page_id' });
});
App.ApplicationRoute = Em.Route.extend({
model: function() {
return this.store.find('lang');
}
});
App.PagesIndexRoute = Em.Route.extend({
model: function(params) {
console.log(params.lang_id);
return this.store.find('page', params.lang_id);
}
});
App.Lang = DS.Model.extend({
name: DS.attr('string'),
pages: DS.hasMany('page',{async:true})
});
<script type="text/x-handlebars" >
<nav>
<ul>
{{#each}}
<li>{{#linkTo 'pages' this currentWhen="pages" activeClass="selected" }}{{name}}{{/linkTo}}</li>
{{/each}}
</ul>
</nav>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="lang/index">
<nav>
<ul class="projects">
{{#each pages}}
<li>{{#link-to "pages.page" this activeClass="selected"}}{{name}}{{/link-to}}</li>
{{else}}
<li>Loading...</li>
{{/each}}
</ul>
</nav>
{{outlet}}
</script>
I'm assuming that the API has changed for how to use adapters but I couldn't find any examples using the fixture adapter. I'm using the new injected store but not sure how to interact with it. I'm just trying to fetch all of the data. Here is a fiddle http://emberjs.jsbin.com/ESoduyA/1/edit.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Ember Starter Kit</title>
<link rel="stylesheet" href="https://rawgithub.com/emberjs/starter-kit/v1.0.0/css/normalize.css">
</head>
<body>
<script type="text/x-handlebars">
<h2>Welcome to Ember.js</h2>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="index">
<ul>
{{#each item in model}}
<li>{{item.type}}</li>
{{/each}}
</ul>
</script>
<script src="https://rawgithub.com/emberjs/starter-kit/v1.0.0/js/libs/jquery-1.9.1.js"></script>
<script src="https://rawgithub.com/emberjs/starter-kit/v1.0.0/js/libs/handlebars-1.0.0.js"></script>
<script src="https://rawgithub.com/emberjs/starter-kit/v1.0.0/js/libs/ember-1.0.0.js"></script>
<script src="http://builds.emberjs.com/beta/ember-data.js"></script>
</body>
</html>
JS
App = Ember.Application.create();
App.Router.map(function() {
// put your routes here
});
App.IndexRoute = Ember.Route.extend({
model: function() {
return this.get('store').findAll('color');
}
});
App.store = DS.Store.create({
adapter: 'DS.FixtureAdapter'
});
App.Color = DS.Model.extend({
type: DS.attr()
});
App.Color.FIXTURES = [
{type: 'blue'},
{type: 'green'}
];
This results in these errors.
Assertion failed: No model was found for 'html' ember-1.0.0.js:394
DEPRECATION: Action handlers contained in an `events` object are deprecated in favor of putting them in an `actions` object (error on <Ember.Route:ember245>)
at Object.triggerEvent (https://rawgithub.com/emberjs/starter-kit/v1.0.0/js/libs/ember-1.0.0.js:30519:13)
at trigger (https://rawgithub.com/emberjs/starter-kit/v1.0.0/js/libs/ember-1.0.0.js:29641:16)
at handleError (https://rawgithub.com/emberjs/starter-kit/v1.0.0/js/libs/ember-1.0.0.js:29903:9)
at invokeCallback (https://rawgithub.com/emberjs/starter-kit/v1.0.0/js/libs/ember-1.0.0.js:8055:19)
at null.<anonymous> (https://rawgithub.com/emberjs/starter-kit/v1.0.0/js/libs/ember-1.0.0.js:8109:11)
at EventTarget.trigger (https://rawgithub.com/emberjs/starter-kit/v1.0.0/js/libs/ember-1.0.0.js:7878:22)
at https://rawgithub.com/emberjs/starter-kit/v1.0.0/js/libs/ember-1.0.0.js:8180:17
at Object.DeferredActionQueues.flush (https://rawgithub.com/emberjs/starter-kit/v1.0.0/js/libs/ember-1.0.0.js:5459:24)
at Object.Backburner.end (https://rawgithub.com/emberjs/starter-kit/v1.0.0/js/libs/ember-1.0.0.js:5545:27) ember-1.0.0.js:394
Error while loading route:
TypeError
ember-1.0.0.js:394
Uncaught TypeError: Cannot set property 'store' of undefined
Here's some info on the FixtureAdapter. http://emberjs.com/guides/getting-started/using-fixtures/
tl,dr :
App.ApplicationAdapter = DS.FixtureAdapter.extend();
App.Color.FIXTURES = [
{id: 1, type: 'blue'},
{id: 2, type: 'green'}
];
Tweaked bin : http://emberjs.jsbin.com/ESoduyA/4/edit
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