following emberjs guide for #linkTo helper does not display individual post - ember.js

I have a jsfiddle with a route as shown below, which is exactly thesame as the one in emberjs guides and when I click on the #linkTo helper attached to {{post.title}}, it ought to show me the individual post but it does not and instead the console shows this errors:
Uncaught Error: assertion failed: Cannot call get with 'id' on an undefined object.
Also when I click the posts link on the home page, it displays all the titles but in the console, it also shows this error:
Uncaught Error: Something you did caused a view to re-render after it rendered but before it was inserted into the DOM.
EmBlog.Router.map(function() {
this.resource("posts", function(){
this.route('show', {path: '/:post_id'}) ;
});
});
The template which is thesame as the emberjs guides
<script type="text/x-handlebars" data-template-name="posts/index">
{{#each post in content}}
<p>{{#linkTo 'posts.show' post}} {{post.title}} {{/linkTo}}</p>
{{/each}}
</script>
I looked at this commit that added support for string literals as param for {{linkTo}} and in particular the suggestions below from that commit:
Now, Ember allows you to specify string literals as arguments. {{#linkTo post popular}} would look up the "popular" property on the current context and generate a URL pointing to the model with that ID. While {#linkTo post "popular"}} would treat the string literal "popular" as the model.

It seems like the only issue was you forget to pass the context to the linkTo posts.edit helper in the posts/show template.
<script type="text/x-handlebars" data-template-name="posts/show">
<h1>Post</h1>
<p>Your content here.</p>
<h3> {{title}} </h3>
<h3> {{body}} </h3>
<br/>
<p> {{#linkTo 'posts.index'}} back {{/linkTo}}</p>
<p> {{#linkTo 'posts.edit' content}} Edit the post {{/linkTo}}</p>
</script>
Here is a working fiddle, BTW I've cleaned up a bit, some things seemed useless for me.
http://jsfiddle.net/rxWzu/9/

Related

Ember Binding Component Template to Models

Hi I have the following Component Template:
test-component.hbs: (produces img tag per model)
{{#each titleModels}}
<div class="item">
<img {{action "owlItemClicked" id index on="click" }} {{bind-attr src=img}}></img>
</div>
{{/each}}
Its used in parent template
parent.hbs:
{{test-component action="titleClicked" parentController=controller titleModels=model}}
On titleClicked action it is suppose to remove the clickedModel and refresh the template to show the removed view.
parent-controller.js:
modelChanged: false,
actions: {
titleClicked: function(){
self.get('model').removeObject(aSelectedModel);
self.set('modelChanged',true);
}
}
The test-component observes changes to titlesModel and rerenders the template:
test-component.js:
titleModelsChanged: function(){
this.rerender();
}.observes('parentController.modelChanged'),
this.rerender methos is called successfully and the specific html tag (e.g the one defined below) for the removed model is no longer present in the DOM for html page generated from test-component.hbs as expected.
<img {{action "owlItemClicked" id index on="click" }} {{bind-attr src=img}}></img>
The img tags for the remaining models are present when inspecting the dom. However they are not displayed out the actual html page ( i dont see the actual imgs), even though the are present in the DOM when I inspect the elements.
How do I display the img tags of the remaining models after rerender on the html page ?
First, two small notes. The <img> tag must not have a closing tag. So no <img></img> but simply <img> (or <img /> alternatively).
The context-changing {{each}} as you use it is deprecated in current and future versions of Ember.js. So you should rewrite your component as
{{#each titleModels as |titleModel|}}
<div class="item">
<img {{action "owlItemClicked" titleModel.id titleModel.index on="click" }} {{bind-attr src=titleModel.img}}>
</div>
{{/each}}
Now to your question. Given that the <img> tags are in the DOM but the actual image is not visible, the problem must be in the src attribute of the images. If you open the URL in the src in a separate tab, do you see the image you're supposed to see?
The JSBin http://emberjs.jsbin.com/mitadovero/edit?html,js,output solves the problem.

ember.js: conditional positioning of nested resource outlet

starting from the bloggr-client of the ember guide i would like to include the outlet of 'post' inside the 'posts' each loop, resulting in some kind of accordeon-like behaviour.
e.g., the router looks like this:
App.Router.map(function() {
this.resource('posts', function() {
this.resource('post', { path: ':post_id' });
});
});
the template (cleared of html tags for legibility) should do something like:
<script type="text/x-handlebars" id="posts">
{{#each model}}
{{#link-to 'post' this}}{{title}}{{/link-to}}
{{#if :post_id given and corresponding with this post}} <-- that's pseudo code ;-)
{{outlet}}
{{/if}}
{{/each}}
</script>
any idea how to accomplish this properly?
UPDATE 1:
to clarify, output on url '/posts' should be:
post 1 title
post 2 title
post 3 title
on url '/posts/1':
post 1 title
complete post 1
post 2 title
post 3 title
on url '/posts/2':
post 1 title
post 2 title
complete post 2
post 3 title
Basically, you want to be able to displays all of the posts on the posts route as an accordion? You're going about it wrong because you can only have one {{outlet}} per template. What you want to do is build a component, which would look something like this:
<script type="text/x-handlebars id="components/post-card">
{{#link-to 'post' post tagName="h2"}}{{post.title}}{{/link-to}}
<p>{{post.snippet}}</p>
</script>
And call it in the posts route like this:
<script type="text/x-handlebars" id="posts">
<ul>
{{#each}} -> if you're iterating through the model, no need to specify
<li>
<h3 {{action makeActive}}>{{title}}</h3>
{{#if active}}
{{post-card post=this}}
{{/if}}
</li>
{{/each}}
</ul>
</script>
You would add active as a property in your model, and makeActive would be an action in your controller that would make active true for the given model, and make the other ones false. This would model an accordion, though your route would not update.

Ember.js {{linkTo}} to itself does not render

I have a problem with a linkTo that points to itself. The actual problem is in an application that has a sidebar with a set of links. The first time a click the link the model and view is loaded and displayed properly. However on the second click the view and/or model disappear.
I've condensed the problem in this jsfiddle. The index route displays a list of links and when clicking on one of the links it will display the detail. In the detail page I have a link to itself but when I click it the model does not show.
The detail template shows the content fine but note the {{firstName}} or {{lastName}}
<script type="text/x-handlebars" data-template-name="item">
<h2>Item Content:</h2>
{{#linkTo "item" id}}Reload me{{/linkTo}}
{{content}}
<ul>
<li>{{firstName}} {{lastName}}</li>
</ul>
</script>
I think the issue is similar to Ember.js - linkTo error on second call
Updated sample
Here is a new example With linkTo at the top levelwhere the {{linkTo}} item is in the top level application template
<script type="text/x-handlebars" data-template-name="application">
{{#linkTo "test" 0}}Test 0{{/linkTo}}
{{outlet}}
</script>
Following #intuitivepixel solution using an action gives me the same result
<script type="text/x-handlebars" data-template-name="application">
<a href="#" {{action reloadMe "test" 0}}>Test 0</a>
{{outlet}}
</script>
Not everything can be done with the {{linkTo}} helper, IMO for this kind of feature (like a reload) you should go for a {{action}} helper instead.
First define the action that does the routing for you when called:
App.TestRoute = Ember.Route.extend({
events: {
reloadMe: function(route, content) {
this.transitionTo(route, content);
}
},
serialize: function(model) {
return {id: model.id};
}
});
And then in your template:
<a href="#" {{action reloadMe "test" content}}>Reload me</a>
See here how you could implement it: http://jsfiddle.net/FSd6H/4/
Hope it helps.

Ember.js: Passing model into view

I have a controller with data about user accounts (icon, name, provider, etc.). Within the output of the each loop I have a view that will build a CSS class dynamically based on the provider passed in via that specific model.
<script type="text/x-handlebars" data-template-name="accountItem">
{{#each account in controller}}
{{#view App.AccountView}}
<h4>{{account.name}}</h3>
<img {{bindAttr src="account.icon"}} />
<i {{bindAttr class="account.provider"}}></i>
{{/view}}
{{/each}}
</script>
App.AccountView = Ember.View.extend({
tagName: 'a',
classNames: ['avatar-image'],
providerClass: function(el) {
// do something
}
});
The question I have is two-fold.
How do you pass in "account", or the currently iterated item, into the view?
After you pass it in, how do you reference it?
I'm sure this is something that happens quite often but I can't seem to find any examples. Can anyone offer some input on this please?
Views has a special content property in a view which allows a more simple approach: you just use a name of the model's property without the view.content. part.
Also, when you're iterating over controller, you can omit the name of loop variable and use this instead, like in this guide. This is not necessary but can make the code a bit cleaner.
Also, from within view's template you generally don't need to reference the outside variables although you can if you like..
{{#each controller}}
{{#view App.IndexView contentBinding="this"}}
<h4>{{name}}</h4>
<img {{bindAttr src="icon"}} />
<i {{bindAttr class="provider"}}></i>
<i> {{icon}} </i>
<i>{{provider}}</i>
{{/view}}
{{/each}}
And you can always access the content property from within the view with:
this.get('content');
The currently iterated item can be passed into the view with the help of property bindings and it can be refered as "{{view.property}}" in the template. For example:
{{#each account in controller}}
{{#view App.IndexView itemBinding="account"}}
<h4>{{view.item.name}}</h3>
<img {{bindAttr src="account.icon"}} />
<i {{bindAttr class="account.provider"}}></i>
<i> {{view.item.icon}} </i>
<i>{{view.item.provider}}</i>
{{/view}}
{{/each}}
I have created a simple jsfiddle for the above case. Do check it and let me know if you were able to resolve the issues.
Fiddle url : http://jsfiddle.net/nCyn6/3/

Change Navbar based on login state

I’ve been trying, using Rails/Ember pre-4, to do a fairly typical thing, that is have a page with a navbar and a content section. The navbar only changes on login (shows logout button when logged in and login and register buttons when logged out), not on every page change.
At first thought i could do something in the application.hbs template such as:
{{view navbar}}
{{outlet}}
where i set up navbar to respond to login state changes (managed by a state manager). This didn’t seem to work.
Then i tried something like (also in application.hbs):
{{outlet navbar}}
{{outlet}}
and tried setting navbar in each route, which results in lots of duplication and also didn’t ultimately work.
Before posting code, wanted to know if anyone already has a good solution to this common situation where certain parts of your page such as a navbar or sidebar only change upon some change in app state, not on every page change.
There are lots of ways to get this done. The first approach you described is closest to what we are doing. In past ember versions we used view helper for this, today we use {{render}} but it's the same basic concept. For example, application.hbs might look like this:
{{render navbar}} {{outlet}}
Now navbar.hbs can use a simple {{#if}} helper to swap links based on login state.
<div class="navbar">
<div class="navbar-inner">
{{#linkTo index class="brand"}}My App{{/linkTo}}
<ul class="nav">
<li>{{#linkTo index}}Home{{/linkTo}}</li>
<li>{{#linkTo about}}About{{/linkTo}}</a></li>
</ul>
<ul class="nav pull-right">
{{#if isAuthenticated}}
<li><a {{action logout}} href="#">Logout</a></li>
{{else}}
<li><a {{action login}} href="#">Login</a></li>
{{/if}}
</ul>
</div>
</div>
Now we add logic to NavbarController that tracks and manages login state.
App.NavbarController = Ember.ArrayController.extend({
isAuthenticated: false,
login: function() {
this.set('isAuthenticated', true);
},
logout: function() {
this.set('isAuthenticated', false);
}
});
In a real app NavbarController would proxy these requests to another controller, perhaps currentUserController. I've created a working sample here: http://jsbin.com/iyijaf/6/edit