emberjs - block params for component - ember.js

If I declare a component like this:
<p>
{{#x-autosuggest source=model destination=tags minChars=0}}
<img src="img/small_avatar.png" title="{{name}}" class="avatar"/>
{{/x-autosuggest}}
</p>
I want the name that field to come from a context I pass using the new block params syntax. I've tried the code sample below but the context is still the context of the controller and not the argument I pass using yield in the component's hbs file.
<ul class='selections'>
{{#each destination as |selection|}}
<li class="selection">
<a class="as-close" {{action "removeSelection" selection}}>x</a>
{{yield selection}}
{{displayHelper selection searchPath}}
</li>
{{/each}}
</ul>
How can pass the selection argument so I can set the name attribute in the original code snippet?
I've recreated a basic example with this jsbin

You need to add as |name| where you're using your component to get the yielded value.
<p>
{{#x-autosuggest source=model destination=tags minChars=0 as |name|}}
<img src="img/small_avatar.png" title="{{name}}" class="avatar"/>
{{/x-autosuggest}}
</p>

Related

Ember Octane - How to loop through model records inside a component?

I have an array of strings passed as an argument to a component, inside the component I am using "each" helper to render each string in a text input. I tried the following approach.
I have a model passed as an argument to a component. I'm using #each helper to iterate through that model and this does not work.
Example:
Template
<div>
<Location::LocationList #model="{{#model}}"/>
</div>
LocationList component:
<ul class="location-list">
{{#each this.args.model as |location|}}
<li>
{{#location.title}}
</li>
{{/each}}
</ul>
And if I just do it in this way:
<ul class="location-list">
{{#each #model as |location|}}
<li>
<Location::LocationItem #location={{location}}/>
</li>
{{/each}}
</ul>
It works as needed.
Any suggestions?
According to the docs on Component Arguments, using the #model as you have in your last snippet,
<ul class="location-list">
{{#each #model as |location|}}
<li>
<Location::LocationItem #location={{location}}/>
</li>
{{/each}}
</ul>
is the correct way to reference arguments.
Referencing args via this.args is reserved for usage in the class body of a component.
the #namedArgs syntax is consistent across class-based components and template-only components as template-only components do not have a this.

Ember passing multiple list items in template

Is it possible to pass multiple list of items in template using {{each}}
Can someone guide me on what I am doing,
in my sales-orders.hbs below is my currenet code.
{{#each model as |detail|}}
<li>{{sales-orders-grid detail=detail}}</li>
{{else}}
Blank
{{/each}}
</ul>
Then calling the sales-orders-grid component
Shipping Method
<div class="col-xs-12 col-md-12 col-sm-12 products-item-products border-left padding10">
<ul>
{{#each shippingMethod as |sm|}}
{{sales-orders-grid-shipping-method sm=sm}}
{{/each}}
</ul>
</div>
In my sales-orders-grid-shipping-method component calling is this:
sm.shippingMethodName
What I'm trying to achieve here is to pass list of items in {{each}} in my main template. Is it possible?
To change scope you can use the "with" helper.
http://emberjs.com/api/classes/Ember.Templates.helpers.html#method_with
{{#with user.posts as |blogPosts|}}
<div class="notice">
There are {{blogPosts.length}} blog posts written by {{user.name}}.
</div>
{{#each blogPosts as |post|}}
<li>{{post.title}}</li>
{{/each}}
{{/with}}
I think you can nest multiple "with" helper.
I think the way to go is to restructure your data as:model.list1,model.list2,etc.
Then pass the model and use as necessary.And use nested each to acheive the grid.
Iam only posting this as an answer because I can't comment yet.
So, do get back to me for Clarifications.

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.

Handling dynamic nested views with Ember + Handlebars

I'm using Ember.js 1.0 pre release and Handlebars 1.0.0 and want to represent a list of comments to a post.
My comment object is this:
// COMMENT ITEM
HaBlog.Comment = Em.Object.extend({
user:null,
text:null,
created: moment().subtract('years', 100),
createdAgo: function(){
return (this.get('created').fromNow());
}.property('created'),
rating:null,
replies:[]
});
And this is my template for the view:
<div id="postComments" class="span10">
<h1>Comments</h1>
{{#each comments}}
<div class="comment">
<small>
<span class="commentDate">
{{createdAgo}}
</span>
</small>
<span class="commentText">
{{text}}
</span>
</div>
{{#each comments.replies}}
<div class="comment">
<small>
<span class="commentDate">
{{createdAgo}}
</span>
</small>
<span class="commentText">
{{text}}
</span>
</div>
{{/each}}
</div>
My problem is that each comment can have a number of replies, which are comments on their own, so they can have more replies.
I have check the nested views in Ember.js and Handlebars, but don't seem to find any way to make it loop through all the replies in a recursive way displaying all the comments in a "tree" way...
I'm having a little trouble understanding exactly what falls under comment vs reply based on your question but I think you should still be able to solve this based on what I suggest below.
What you'll want to do is use an Ember.CollectionView and define a view class that you'll use as the itemViewClass on the collection view. So your itemViewClass would be something like CommentView, and what have a template like:
Comment Text: {{text}}
Replies: {{view Ember.CollectionView content=replies itemViewClass=HaBlog.CommentView}}
This is the only way to handle the problem of recursion, which, like you said, can't really be handled with Handlebars only.

Ember.js binding a css style in a template

This is solved since Ember 1.8 with the HTMLBars engine.
I would like to bind a css style in a template. What would be the
solution ?
I tried this:
<div class="bar" style="width:{{barWidth}}px"></div>
but DOM element look like this after its been rendered:
<div class="bar" style="width:<script id='metamorph-28-start' type='text/x-placeholder'></script>5.000000000000002<script
id='metamorph-28-end' type='text/x-placeholder'>px">
Obviously here we can see that the tag for metamorph was
added within the style attribute...
I'm wondering what is the best way to achieve such things with
Ember.js
There is something i don't get yet.
I have a template as follow:
<script type="text/x-handlebars" data-template-name="listTemplate">
<ul id="list">
{{#each App.list}}
<li {{bindAttr data-item-id="itemId"}}>
<div>
<span class="label">{{itemName}}</span>
<div class="barContainer">
<div class="bar" {{bindAttr style="barWidth"}}></div>
<div class="barCap"></div>
</div>
</div>
</li>
{{/each}}
</ul>
i'm in a for each loop that loops thru my ArrayProxy content... and the bar width vary depending of the value of each item in the list. Your solution here will not work as the view is the UL and i need a barWidth per model item. and I do not want to polute my Model with css related things like "width: ###px"
Is there any other elegant way to solve what i try to do ? maybe it would be radically different. I'm very new to ember.js and try to discover the best-practices yet:)
Set a string on your view that looks like "width: 100px" and then bind it to your div with the bind-attr helper like so: <div {{bind-attr style="divStyle"}}>Test</div>
http://jsfiddle.net/tomwhatmore/rearT/1/
To simplify all that, I created a tiny handlebars helper for emberjs that allows you to bind any style properties. You can look at https://github.com/yderidde/bindstyle-ember-helper
Add unbound:
<div class="bar" style="width:{{unbound barWidth}}px"></div>
In Ember 2.0:
<div class="bar" style="width:{{barWidth}}px"></div>
will just work.