I have a jsfiddle example, that I cannot apply a FixtureAdapater to. I am terrible at ember and am trying to learn but I cannot get this to work. Any help would be much appreciated, thank you so very much
HTML
<body>
<script type="text/x-handlebars" data-template-name="MessageManager">
<ul>
{{#each item in model}}
<li>{{item}}</li>
{{/each}}
</ul>
</script>
</script>
</body>
JAVASCRIPT
window.MessageManager = Ember.Application.create();
MessageManager.Store = DS.Store.extend({
revision: 13,
adapter: DS.FixtureAdapter.create()
});
MessageManager.Router.map(function() {
this.resource('MessageManager',{path :'/'});
});
MessageManager.MessageManagerRoute = Ember.Route.extend({
model: function() {
var x = this.store.find('Message');
}
});
MessageManager.Message = DS.Model.extend({
id:DS.attr('id'),
SendingPhoneNumber : DS.attr('string'),
ReceivingPhoneNumber : DS.attr('string'),
DateReceived : DS.attr('date')});
MessageManager.Message.FIXTURES = [
{
id:1,
SendingPhoneNumber :'555 555 9219',
ReceivingPhoneNumber :'555 555 1646',
Message : 'Why Do i have a 5 dollar charge on my phone bill',
DateReceived :'2014-02-21'
},
{
id:2,
SendingPhoneNumber :'555 555 9219',
ReceivingPhoneNumber :'555 555 1678',
DateReceived :'2014-02-18'
}];
There were a couple of errors a fixed version in on jsbin. I'm not sure which version of ember-data you're using, but ember-data changed the way you set the adapter, you set a factory instead of an instance:
adapter: DS.FixtureAdapter
Instead of:
adapter: DS.FixtureAdapter.create()
Also, there's no need to set the id attribute on your model definition and you have an extra closing tag for the script element.
Hope this helps.
Related
When I try to render a list of view models contained in a chart model using the each handlebars helper, the promise array for the view models doesn't resolve before the each helper renders, leaving blank lis:
template:
<script type="text/x-handlebars" id="chart-container">
{{views}}
<ul>
{{#each view in views}}
<li>{{view}}</li>
{{/each}}
</ul>
</script>
What's odd is that if I change the each helper to {{#each views}} it works fine.
How can I make the view render once the promised hasMany relationship has been resolved using view in views for the each helper? Below are the relevant models and fixtures:
displayItem model:
var DisplayItem = DS.Model.extend({
name: DS.attr("name"),
display: DS.belongsTo("display", {async: true})
});
chart model:
var Chart = DisplayItem.extend({
views: DS.hasMany("view", {async: true})
});
view model:
var View = DS.Model.extend({
name: DS.attr("string"),
chart: DS.belongsTo("chart", {async: true})
});
relevant fixture data:
Chart.FIXTURES = [
{
id: 1,
name: "Derp",
display: 1,
views: [1, 2],
defaultView: 1
}
];
View.FIXTURES = [
{
id: 1,
name: "Test 1",
chart: 1
},
{
id: 2,
name: "Test 2",
chart: 1
}
];
To answer your question, the route is simplest place to do it. Using nested promises Ember won't setup the controller etc, until the deepest promise has resolved.
App.ChartContainerRoute = Em.Route.extend({
model: function(){
return this.store.find('chart').then(function(charts){
return Em.RSVP.all(charts.getEach('views')).then(function(){
return charts;
});
});
}re
});
Generally I'd recommend against waiting on all of the async calls (since Ember will asynchronously inject them into the page). If you are trying to modify the view after it's been inserted, there are other patterns that can solve this while giving a more responsive feeling app.
The real problem you're seeing
You aren't specifying anything to show in the li, and you're using a key word view
<li>{{view.name}}</li>
http://emberjs.jsbin.com/OxIDiVU/790/edit
view usually refers to the view associated with the current template etc.
{{#each item in views}}
<li>{{item}}</li>
{{/each}}
http://emberjs.jsbin.com/OxIDiVU/791/edit
After endless trying I hope someone find the clue in what I am trying. I know there are many questions about this specific topic on stackoverflow. However I think I do not ask the same question. As I do not find the answer to my specific challenge.
Here is my Router:
App.Router.map(function () {
this.resource('article', {path: '/article/:id'});
this.resource('article.new', {path: "/article/new"});
});
Routes
App.ArticleRoute = Ember.Route.extend({
model: function (params) {
return this.store.find('article', params.id);
}
});
App.ArticleNewRoute = Ember.Route.extend({
renderTemplate: function () {
this.render('article', {
controller: 'article.new'
});
},
model: function () {
return this.store.createRecord('article');
}
});
The model
App.Category = DS.Model.extend({
name: DS.attr('string'),
image: DS.attr('string'),
categoryRelation: DS.belongsTo('category')
});
App.Article = DS.Model.extend({
name: DS.attr('string'),
category: DS.hasMany('category')
)};
The returned JSON from server:
{
"articles":[
{
"id":1,
"name":"Car 1",
"category":[1,2],
{
"id":2,
"name":"Car 2",
"category":2,
],
"categorys":[ // note the added 's' when returning multiple items as per EmberJS convention
{
"id":1,
"name":"Oldtimers"
},
{
"id":2,
"name":"Classic"
}
],
}
And now the question, because I try in my template the following:
<script type="text/x-handlebars" data-template-name="article">
<div>
{{#each category in model}}
{{category.name}}<br>
{{name}}<br>
{{/each}}
</div>
</script>
I have tried multiple variations in the template, this is my last code which seems correct. Note: as for article with id 2, the template must also render if there is just one article.
Edit: I translated some code for you guys. If there are misspellings, they are probably not in the original code.
Your article template will receive just one article so this {{#each category in model}} don't work, you need to use {{#each category in model.category}}:
<div>
Article {{name}}<br/>
{{#each category in model.category}}
Category {{category.name}}<br/>
{{/each}}
</div>
This is a fiddle with this in action http://jsfiddle.net/marciojunior/fj26R/
I'm new to Ember, and I'm following along with their Todo tutorial and making a basic app to create blog posts, adjust their code for my purposes. The app was working fine until I added an itemController to the template and a controller to handle the isCompleted event. Rather than showing the content, as it did before, it shows: <Posts.Post:ember257:1> which appears to be the model name rather than content. The Ember inspector says the model has the right attribute. It just doesn't display properly. Here's some code:
<script type="text/x-handlebars" data-template-name="posts">
<section id="postapp">
<section id="main">
<ul id="post-list">
// new code added
{{#each itemController="post"}}
<li {{bind-attr class="isCompleted:completed"}}>
{{input type="checkbox" checked=isCompleted class="toggle"}}
<label>{{title}}</label>
<p>{{content}}</p>
</li>
{{/each}}
</ul>
</section>
</section>
</script>
And the relevant JavaScript (see the bottom at PostController to see the only change after the code worked):
Posts.Post = DS.Model.extend({
title: DS.attr('string'),
content: DS.attr('string'),
isCompleted: DS.attr('boolean')
});
Posts.Post.FIXTURES = [
{
id: 1,
title: "JavaScript: The Dark Side",
content: "Here is a bunch of information on the dark side of " +
"Javascript. Welcome to hell!"
},
{
id: 2,
title: "The glory of underscore",
content: "Here, we're going to talk about the many uses of the " +
"underscore library. Read on!"
},
{
id: 3,
title: "Objectifying Objects",
content: "Objects are confusing, eh? Let's play around with objects " +
"a bit to see how to really use them."
}
];
// This is the only code that changed before the app was functioning properly
Posts.PostController = Ember.ObjectController.extend({
isCompleted: function(key, value){
var model = this.get('model');
if (value === undefined) {
// property being used as a getter
return model.get('isCompleted');
} else {
// property being used as a setter
model.set('isCompleted', value);
model.save();
return value;
}
}.property('model.isCompleted')
});
Any insight as to why the right content isn't displayed would be greatly appreciated.
I just figured out the problem. content is a property all Ember controllers, so my variable name for the post content was creating some confusion when Ember was rendering the page. When I changed the variable name in my model and other places to post_content, content was rendering properly in the page.
// template
{{#each itemController="post"}}
<li {{bind-attr class="isCompleted:completed"}}>
{{input type="checkbox" checked=isCompleted class="toggle"}}
<label>{{title}}</label>
<p>{{post_content}}</p>
</li>
{{/each}}
//model
Posts.Post = DS.Model.extend({
title: DS.attr('string'),
post_content: DS.attr('string'),
isCompleted: DS.attr('boolean')
});
And problem solved.
This is model
App.Store = DS.Store.extend({
revision: 12,
adapter: DS.FixtureAdapter
});
App.Markets = DS.Model.extend({
ids: DS.attr("string"),
name: DS.attr("string"),
created: DS.attr("string")
});
App.Markets.FIXTURES = [
{ids:"312", name:"joy", created:"2012/1/1"},
{ids:"412", name:"adel", created:"2012/1/2"},
{ids:"512", name:"john", created:"2012/1/3"}
];
App.Sources = DS.Model.extend({
source_channel: DS.attr("string"),
handle: DS.attr("handle")
});
App.Sources.FIXTURES = [
{source_channel:"sc1", handle: "hn1"},
{source_channel:"sc2", handle: "hn2"}
];
This is route.
var App = Ember.Application.create();
App.Router.map(function() {
this.resource('markets', {path: '/markets'}, function() {
this.resource("sources", { path: "/:market_id" });
});
});
App.MarketsRoute = Ember.Route.extend({
model: function () {
return App.Markets.find();
}
});
App.SourcesRoute = Ember.Route.extend({
model: function(){
return App.Sources.find();
}
});
This is template
<script type="text/x-handlebars" id="_sources">
{{#each sources in content}}
<span>{{sources.handle}}</span>
<span>{{sources.sources_channel}}</span>
{{/each}}
</script>
<script type="text/x-handlebars" id="markets">
{{#each markets in content }}
{{#linkTo 'sources' markets.ids class="test" }}<span>Source</span>{{/linkTo}}
<span>{{markets.name}}</span>
<span>{{markets.created}}</span>
{{/each}}
<div class="sources">
{{partial "sources"}}
</div>
</script>
When I go to /#/markets, I can see the markets lists. This is correct.
Focus in {{#linkTo 'sources' markets.ids class="test" }}Source{{/linkTo}} of markets template.
In here, markets.ids doesn't work.
I'd like to go to /#/markets/markets_id when I click the link.
Along with passing the object to the sources route in linkTo,
define serialize method in your App.SourcesRoute.
The template:
{{#linkTo 'sources' markets class="test" }}<span>Source</span>{{/linkTo}}
The Route:
App.SourcesRoute = Ember.Route.extend({
model: function(){
return App.Sources.find();
},
serialize: function(model) {
return { market_id: model.ids };
}
});
You want to use linkTo 'sources' markets instead. ie:- pass the model in the each loop to the `linkTo.
Note: Regarding your naming conventions. Ember likes models to be singular, and Routes/Controllers plural or singular depending on whether the route points to one or more models.
Edit: Clarification.
Change the linkTo to this,
{{#linkTo 'sources' markets class="test" }}<span>Source</span>{{/linkTo}}
What I'm trying to do is very basic but I'm having very little luck...
Simply enough, I don't want to display a chunk of HTML until a certain Ember Data model property is fully loaded.
As you can see from the jsfiddle, the parent model: App.Person gets loaded into the DOM and it also loads the 3 placeholders for its hasMany property belts.
It then executes the request to populate App.Belt and fills in the placeholders.
While this is usually ok, it makes a big mess of things when trying to build an SVG, for example. Since the surrounding <svg> tags will get appended to the DOM immediately and then some time down the track (once the asynchronous request returns data), the inner svg components will be added between the tags. This usually creates browser rendering errors.
TL;DR
In the example, how do I defer the <h3>...</h3> section of the template from being added to the DOM until the model data and its relationships (belts) are fully loaded? This way everything gets visually and physically added to the DOM at once.
The JS:
// Create Ember App
App = Ember.Application.create();
// Create Ember Data Store
App.store = DS.Store.create({
revision: 11,
//Exagerate latency to demonstrate problem with relationships being loaded sequentially.
adapter: DS.FixtureAdapter.create({latency: 5000})
});
// Create parent model with hasMany relationship
App.Person = DS.Model.extend({
name: DS.attr( 'string' ),
belts: DS.hasMany( 'App.Belt' )
});
// Create child model with belongsTo relationship
App.Belt = DS.Model.extend({
type: DS.attr( 'string' ),
parent: DS.belongsTo( 'App.Person' )
});
// Add Parent fixtures
App.Person.FIXTURES = [{
"id" : 1,
"name" : "Trevor",
"belts" : [1, 2, 3]
}];
// Add Child fixtures
App.Belt.FIXTURES = [{
"id" : 1,
"type" : "leather"
}, {
"id" : 2,
"type" : "rock"
}, {
"id" : 3,
"type" : "party-time"
}];
// Set route behaviour
App.IndexRoute = Ember.Route.extend({
model: function() {
return App.Person.find();
},
renderTemplate: function() {
this.render('people');
}
});
The HTML/HBS:
<script type="text/x-handlebars">
<h1>Application</h1>
{{outlet}}
</script>
<script type="text/x-handlebars" id="people">
<h3>Don't load this header until every belt defined in App.Person.belts is loaded</h3>
<ul>
{{#each controller}}
{{debugger}}
<li>Id: {{id}}</li>
<li>Name: {{name}}</li>
<li>Belt types:
<ul>
{{#each belts}}
<li>{{type}}</li>
{{/each}}
</ul>
</li>
{{/each}}
</ul>
</script>
The fiddle: http://jsfiddle.net/zfkNp/4/
Check for the controller.content.length and belts.isLoaded, See the jsfiddle for a solution.
<script type="text/x-handlebars" id="people">
{{#if controller.ready}}
<h3>Don't load this header until every belt defined in App.Person.belts is loaded</h3>
{{/if}}
<ul>
{{#each controller}}
{{debugger}}
{{#if belts.isLoaded}}
<li>Id: {{id}}</li>
<li>Name: {{name}}</li>
<li>Belt types:
<ul>
{{#each belts}}
<li>{{type}}</li>
{{/each}}
</ul>
</li>
{{/if}}
{{/each}}
</ul>
</script>
App.IndexController = Ember.ArrayController.extend({
content: null,
ready:function() {
return this.get('content.length')>0
}.property('content.length')
});