Is there itemController for new each syntax in Ember? - ember.js

The new syntax
{{#each pages as |page| itemController="listedPage"}}
causes parse error. Is item Controller usable with the new "each" syntax?
If yes, how to specify it? If not, what is the preferred way to use computed properties with the items of "each"?

Controllers are being phased out - so I would recommend using components..
Component for Each Item
You could implement a 'listed-page' component which would look something like this:
Your template:
<ul>
{{#each pages as |page|}}
{{listed-page page=page}}
{{/each}}
</ul>
The component:
## components/listed-page.js
export default Ember.Component.extend({
tagName: 'li',
page: null,
pageNumberFancy: function() {
return '^'+this.get('page.number')+'^';
}.property('page.number')
})
## templates/components/listed-page.hbs
Number: {{page.number}} ({{pageNumberFancy}})
The output:
<div class='template-level'>
<ul class='template-level'>
<li class='listed-page-level'>Number: 1 (^1^)</li>
<li class='listed-page-level'>Number: 2 (^2^)</li>
</ul>
</div>
Component for the List
Or a listed-pages component - if 'pages' is an array computed property - or both:
Your template:
{{listed-pages pages=pages}}
The component:
## components/listed-pages.js
export default Ember.Component.extend({
tagName: 'ul',
pages: null,
pagesPlusOne: function() {
var pagesList = this.get('pages');
pagesList.addObject(specialPage);
return pagesList;
}.property('pages.[]')
})
## templates/components/listed-pages.hbs
{{#each pagesPlusOne as |page|}}
{{listed-page page=page}}
{{/each}}
The output:
<div class='template-level'>
<ul class='listed-pages-level'>
<li class='listed-page-level'>Number: 1 (^1^)</li>
<li class='listed-page-level'>Number: 2 (^2^)</li>
<li class='listed-page-level'>Number: +1 (^+1^)</li>
</ul>
</div>

Related

How do I pass a value from one .hbs file to another

I am trying to pass the index value from posts.hbs to the delete-post.hbs and then from delete-post.hbs to my delete-post.js function.
posts.hbs
<br>
<h2> Blog Posts </h2>
<ul>
{{#each model as |onePost index|}}
<li id = {{index}}>{{onePost.title}} {{delete-post}}
</li><br>
{{/each}}
</ul>
{{add-new-post}}
delete-post.hbs
<a class="ui red button" {{action 'deletePost' parentNode.id `}}>Delete</a>`
delete-post.js
import Component from '#ember/component';
export default Component.extend
({
actions:
{
deletePost(input)
{
alert(input);
}
}
});
You can pass the parameter by = operator like {{component-name componentProperty=outerProperty. In your case:
{{#each model as |onePost index|}}
<li id = {{index}}>{{onePost.title}} {{delete-post parentNodeId=index}}
</li><br>
{{/each}}
Also, you should change parentNode.id to parentNodeId in your delete-post.hbs

Problems retrieving data from controller using Ember.js 2.3.0

I am trying to learn ember following this course and I have the following controller
import Ember from 'ember';
export default Ember.Controller.extend({
title:'My Blog Post',
body:'Body of the post',
authors:['Author1', 'Author2', 'Author3'],
comments:[
{
name:'name 1',
comment:'comment 1'
},
{
name:'name 2',
comment:'comment 2'
},
{
name:'name 3',
comment:'comment 3'
}
]
});
And Template:
<h1>{{title}}</h1>
<p>{{body}}</p>
<p>
<strong>Authors:</strong>
{{#each authors}}
{{this}},
{{/each}}
</p>
<h4>Comments</h4>
<ul>
{{#each comments as c}}
<li><strong>{{name}}</strong> - {{comment}}</li>
{{/each}}
</ul>
And it has been generating this output:
My Blog Post
Body of the post
Authors: <my-app#controller:post::ember424>, <my-app#controller:post::ember424>, <my-app#controller:post::ember424>,
Comments
-
-
-
I double check everything and it is identical to the demo I am seem, I also try to use {{#each comments as |c|}}, {{each authors as author}} {{this.author}}, try to use {{c.name}}, also try {{this.name}}, {{this.c.name}}
Any ideas where I am going wrong?
Thanks in advance
Change your template file to this:
<h1>{{title}}</h1>
<p>{{body}}</p>
<p>
<strong>Authors:</strong>
{{#each authors as |author|}}
{{author}},
{{/each}}
</p>
<h4>Comments</h4>
<ul>
{{#each comments as |c|}}
<li><strong>{{c.name}}</strong> - {{c.comment}}</li>
{{/each}}
</ul>

each vs each foo in model, differences and issue with link-to undefined

I'm trying to do a list of product items and make them so when you click the image or title it will show a single page/template with the more info, etc.
But, when ever I use {{#each product in model}} the link-to just returns an undefined.
Heres what I have
App.Router.map(function(){
this.route('about', { path: '/aboutus' } );
this.resource('products');
this.resource('product', { path: '/products/:title' } );
this.resource('contacts');
});
App.ProductsRoute = Ember.Route.extend ({
model: function(){
return App.PRODUCTS;
}
});
// Logging out Params from the Route
App.ProductRoute = Ember.Route.extend ({
model: function(params){
return App.PRODUCTS.findBy('title', params.title);
}
});
App.PRODUCTS = [
{
title: 'Flint',
price: 99,
description: 'Flint is a hard, sedimentary cryptocrystalline form of the mineral quartz, categorized as a variety of chert.',
isOnSale: true,
image: 'images/flint.png'
},
{
title: 'Kindling',
price: 249,
description: 'Easily combustible small sticks or twigs used for starting a fire.',
isOnSale: false,
image: 'images/kindling.png'
}
];
when I use this method {{#each product in model}} i get undefined
<script type='text/x-handlebars' data-template-name='products'>
<h1>Products</h1>
<ul class="list-unstyled col-md-8">
{{#each product in model}}
<li class='row m-b'>
{{#link-to 'product' this }}<img {{bind-attr src='product.image'}} class='img-thumbnail col-md-5' alt='product-image' />{{/link-to}}
<div class="col-md-7">
<h2>{{product.title}}</h2>
<p class="product-description">{{product.description}}</p>
<p><button class="btn btn-success">Buy for ${{product.price}}</button></p>
</div>
</li>
{{/each}}
</ul>
</script>
<script type='text/x-handlebars' data-template-name='product'>
<div class="row">
<div class="col-md-7">
<h2>{{title}}</h2>
<p>{{description}}</p>
<p>Buy for ${{price}}</p>
</div>
<div class="col-md-5">
<img {{bind-attr src='image'}} class='img-thumbnail img-rounded' />
</div>
</div>
</script>
but when I use just {{#each}} it returns normally BUT it warns me this: DEPRECATION: Using the context switching form of {{each}} is deprecated. Please use the keyword form ({{#each foo in bar}}) instead.
<script type='text/x-handlebars' data-template-name='products'>
<h1>Products</h1>
<ul class="list-unstyled col-md-8">
{{#each}}
<li class='row m-b'>
{{#link-to 'product' this }}<img {{bind-attr src='image'}} class='img-thumbnail col-md-5' alt='product-image' />{{/link-to}}
<div class="col-md-7">
<h2>{{title}}</h2>
<p class="product-description">{{description}}</p>
<p><button class="btn btn-success">Buy for ${{price}}</button></p>
</div>
</li>
{{/each}}
</ul>
</script>
which one should I use and how do I fix the undefined error? I'm guessing it has to do with the App.ProductRoute but can't figure it out, still new to ember :l
You should use
{{#each product in model}}
and to fix your undefined use the following:
{{#link-to 'product' product }} ...title... {{/link-to}}
When you use {{#each}} the context of this gets switched to each item in the loop, which is sometimes confusing and is being deprecated. When you use the {{#each product in model}} version, the context of each item through the loop is product and this remains whatever it was you entered each

Create a <li class="active"> around an active {{linkTo}}

What is the cleanest way to get <li class="active"> for the active page in the following Ember app?
index.html
<script type="text/x-handlebars">
<ul class="nav">
<li>{{#linkTo 'ping'}}Ping{{/linkTo}}</li>
<li>{{#linkTo 'pong'}}Pong{{/linkTo}}</li>
</ul>
</script>
app.js
App = Ember.Application.create()
App.Router.map(function() {
this.route("ping", { path: "/ping" });
this.route("pong", { path: "/pong" });
});
This workaround did it for me:
{{#linkTo 'menus.search' tagName='li' href=false}}
{{#linkTo 'menus.search'}}
<i class="icon-search"></i>
{{/linkTo}}
{{/linkTo}}
It creates an li element containing an anchor element. And both will be updated with the "active" class when the route is active.
replace in your template the li tags like so:
index.html
<script type="text/x-handlebars">
<ul class="nav">
{{#linkTo 'ping' tagName="li"}}Ping{{/linkTo}}
{{#linkTo 'pong' tagName="li"}}Pong{{/linkTo}}
</ul>
</script>
the {{linkTo}} with the tagName specified will apply a css class name of 'active' automatically when the application's current route matches the supplied route name.
example, when your app url is at /#/ping the resulting markup would be something like:
...
<li class="active">Ping</li>
...
Or you create a custom view
App.ItemView = Ember.View.extend({
tagName: 'li',
classNameBindings: ['active'],
active: function() {
return this.get('childViews.firstObject.active');
}.property()
});
and then use it like so
<script type="text/x-handlebars">
<ul class="nav">
{{#view App.ItemView}}
{{#linkTo 'ping'}}Ping{{/linkTo}}
{{/view}}
{{#view App.ItemView}}
{{#linkTo 'pong'}}Pong{{/linkTo}}
{{/view}}
</ul>
</script>
some css to see it actually working
li a {
color: #000;
}
li a.active {
color: #f00;
}
hope it helps
Just nest the {{link-to}} with a tagName on the outer one. This will set an active class on both the outer <li> and the inner <a> tag.
{{#link-to "ping" tagName="li"}}
{{#link-to "ping"}}ping{{/link-to}}
{{/link-to}}
{{#link-to "pong" tagName="li"}}
{{#link-to "pong"}}pong{{/link-to}}
{{/link-to}}

Setting the id on element created by #each helper

How can I set the id for elements created by the Ember.js handelbars helper #each?
If you take a look at http://jsfiddle.net/7QL5z/ I tried to define an id on calling the #each helper.
The resulting HTML looks like this:
<div id="ember191" class="ember-view">
<ul>
<li id="ember349" class="ember-view"> Animal - Animals </li>
<li id="ember389" class="ember-view"> Android - Androids </li>
<li id="ember427" class="ember-view"> Human - Humans </li>
</ul>
</div>
Neither the div nor the ul (that would be the most usable way) get the specified id.
Is it possible at all? If not: how can I access these elements via Ember?
I tried setting 'elementId' instead of 'id' on the '#each' but it didn't seem to work either...
Otherwise you can create an animals list view
App.AnimalsListView = Ember.CollectionView.extend({
tagName: 'ul',
contentBinding: 'App.itemsController.content',
classNames: ['animals'],
elementId: 'animalsList',
itemViewClass: Ember.View.extend({
classNames: ['animal'],
templateName: 'ember/templates/animals/animal',
elementId:Ember.computed(function(){
'animal-'+this.getPath('content.name')
})
})
});
In your animal template:
{{ content.get('name') }} - {{ content.get('pluralized') }}
And finally in your main html file
<script type="text/x-handlebars">
{{ view App.AnimalsListView }}
</script>
You can just specify the id on a view using id="whatever", but it won't work on a {{#each}}
http://jsfiddle.net/tomwhatmore/TJvR6/
Might be a slightly more elegant solution but what I've put in that js fiddle seems to work.