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

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

Related

How do I change a value in a .hbs file

posts.hbs
I want to add a suffix to the "onePost.id" value and it has to be done in this file.
<br>
<h2> Blog Posts </h2>
<ul>
{{#each model as |onePost index|}}
<li id = {{index}}>{{onePost.title}} {{edit-post id = onePost.id + 'suffix' }}
</li><br>
{{/each}}
</ul>
{{add-new-post}}
Use the concat template helper:
<li id={{index}}>{{onePost.title}} {{edit-post id=(concat onePost.id 'suffix')}}

Binding class from an array in Ember.js

I'm starting with Ember.js and I'm feeling a bit lost.
I have an object like this:
App.BRANDS = [
{
brand:'Audi'
},{
brand:'BMW'
},{
brand:'Skoda'
}];
So what I'm trying is to display all the elements in that object with the {{#each}} component, show the text inside and bind the same text as a className. So I code this in the route:
App.InsuranceAutoSelectBrandRoute = App.Route.extend({
model: function(){
return App.BRANDS;
}
});
And this in the template:
<article>
{{#each brand in model tagName='ul'}}
<li class='item-space'>
<span {{bind-attr class=':brand-auto classNameAuto'}}></span>
{{brand.brand}}
</li>
{{/each}}
</article>
Then the issue is that the name of each brand, before I bind it as a class attr I have to lowercase it...
App.InsuranceAutoSelectBrandController = Ember.Controller.extend({
classNameAuto: function() {
App.BRANDS.forEach(function(item, index){
return item.brand.toLowerCase();
});
}.property()
});
If in the same point where I'm returning the value I make a log, it works, but the class attr is not showing.
What I'd like:
<article>
<li class='item-space'>
<span class='brand-auto audi'}}></span>
Audi
</li>
<li class='item-space'>
<span class='brand-auto bmw'}}></span>
BMW
</li>
<li class='item-space'>
<span class='brand-auto skoda'}}></span>
Skoda
</li>
</article>
Forgive me for my English level and thank you
First, as #Kitler said, bind-attr is deprecated. If you are using 1.13.x or higher, you may just insert class as any other variable, {{brand.brand}}.
Second, your code is incorrect and will not work. The easiest way to do what you want is via helper. You need to create a helper, lower-case and use it in this way:
<article>
<ul>
{{#each model as |brand|}}
<li class='item-space'>
<span class='brand-auto {{lower-case brand.brand}}'>{{brand.brand}}</span>
</li>
{{/each}}
</ul>
</article>
How to create a helper you may learn from documentation (http://guides.emberjs.com/v1.13.0/templates/writing-helpers/). If you use ember-cli, following code should work:
//app/helpers/lower-case.js
import Ember from 'ember';
export default Ember.Handlebars.makeBoundHelper(function (str) {
return str.toLowerCase();
});

Is there itemController for new each syntax in Ember?

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>

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

How can I click to edit on a text field with ArrayController?

I was following the tutorial but the tutorial is for the object controller. In an Array controller how do I properly pass in the object for the text field so it triggers the update for that model object?
Right now I can double click, and then type in some value, and if I hit enter I get the value plus undefined method set.
Uncaught TypeError: Object asdasdasdasdasd has no method 'set'
I guess it's passing the raw value into the controller and then trying to run methods off of that. How do I get it to pass the actual model?
View:
<ul>
{{#each}}
<li {{bind-attr class="isEditing:editing"}} {{action "editWorkout" this on="doubleClick"}}>
{{#if isEditing}}
{{view Ember.TextField class='edit' action="updateWorkout"}}
{{else}}
{{#link-to 'workout' this}} {{title}} {{/link-to}}
{{/if}}
</li>
{{/each}}
<li>
{{newWorkoutName}}
</li>
</ul>
Controller:
EmberWorkouts.WorkoutsController = Ember.ArrayController.extend
actions:
editWorkout: (workout) ->
workout.set('isEditing', true)
createWorkout: ->
title = #get('newWorkoutName')
workout = #store.createRecord('workout', title: title)
#set('newWorkoutName', '')
workout.save()
updateWorkout: (workout) ->
workout.set('isEditing', false)
workout.save()
isEditing: false
Repo here if you want to investigate: https://github.com/ecl1pse/ember-workouts/tree/master/app
You can specify an itemController in your each and then use an ObjectController for each item in your list.
{{#each itemController="workout"}}
<li {{action editWorkout on="doubleClick"}}>
<!-- Other stuff goes here -->
</li>
{{/each}}
EmberWorkouts.WorkoutsController = Ember.ObjectController.extend({
editWorkout : function(){
this.set('isEditing', true);
}
});
Here's a JSBin of the general idea : http://jsbin.com/ucanam/1038/edit