Is there a way to combine polymer firebase-collection with iron-list?
I'm able to show my data with firebase-collection, but I also want to use iron-list to style my elements...
<firebase-collection data="{{games}}"
location="url">
</firebase-collection>
<template is="dom-repeat" items="{{games}}" as="game">
<div>
<span>{{game.home}}</span>
<span class="game_score">
<span>{{game.home_score}}</span> - <span>{{game.away_score}}</span>
</span>
<span>{{game.away}}</span>
</div>
</template>
Related
<div class="ui form segment">
<div class="field">
<div class="ui selection dropdown" tabindex="0">
<div class="default text">
Select
</div>
<i class="dropdown icon"></i><input name="hidden-field" type="hidden">
<div class="menu" tabindex="-1">
<div class="item" data-value="1">
Choice 1
</div>
<div class="item" data-value="2">
Choice 2
</div>
</div>
</div>
</div>
</div>
this code is written inside a template.hbs(handlebar) file.
I want to initialise the drop down with the following command
$('.ui.dropdown')
.dropdown();
where could I write the second code?
if it was an html/php file I could write inside the template
Short answer, you don't.
Long answer:
If you are developer who takes any pride in his work and doesn't want the next maintainer to fantasize about drowning you in dirty toilet water, you should create a dropdown component. This component seems small in scope and would look something like this:
{{dropdown-list options=listOfOptions onOptionSelect=(action "someAction")}}
You pass in the options, convert:
<div class="menu" tabindex="-1">
<div class="item" data-value="1">
Choice 1
</div>
<div class="item" data-value="2">
Choice 2
</div>
</div>
to:
<div class="menu" tabindex="-1">
#{{each options as |option|}}
<div class="item" data-value="{{option.value}}">
option.displayName
</div>
{{/each}}
</div>
where each options is [{displayName: "Option 1", value: 1}...]
Inside of the javascript part of the component, simply execute the above code from within didInsertElement which the docs describe:
After a component successfully renders its backing HTML element into the DOM, it will trigger its didInsertElement() hook.
Lastly, inside of the component, bind listeners to the dropdowns native events. One such function, the one for the dropdown's select action, should call this.onOptionSelect(whateverTheSelectedValueIs). This allows you to define actions differently for each dropdown.
I highly recommend you take a moment to read this section of the docs
Writing Ember requires a different mindset than writing backend rendered html + jquery style applications. You want to really decouple your javascript code from the DOM as much as possible and focus on values + data down/actions up. Components are the correct place to bind to native javascript events and integrate with 3rd party addons. Doing so effectively isolates the DOM interactions and provides a nicer api to the rest of your application. If you were to just use the routes renderTemplate hook to execute the .dropdown() call, you require every developer to remember to call dropdown any time you want to use a dropdown and have done absolutely nothing for reusability and just hacked your way to a solution. Don't be that guy, do it right :)
I can seem to find a good answer for my problem. I have a sidebar template which contains a div for each item my model contains. When I have hundreds of items to render, it takes up to 8-10 seconds to render the template. I am using ember-data.
How can I render the items that are loaded before it finishes fetching the entire model?
Here is my template :
{{#each conv in model itemController='singleconv'}}
{{#if (equals conv.url selectedSubuserEmail)}}
<div class="conversation-content-wrapper" {{action "clickConv" conv preventDefault=false}}>
<div class="history-message-assigned in-progress-closed" style="display:none;"><p><i class="icon-x"></i>Conversation closed</p></div>
<div class="history-message-assigned in-progress-assignation" style="display:none;"><p><i class="icon-assign"></i>Conversation assigned</p></div>
<div class="history-message-assigned in-progress-reopen" style="display:none;"><p><i class="icon-re-opened"></i>Conversation re-opened</p></div>
<div class={{conv.selectedClass}}>
<div class="conversation-time-history">{{{conv.status}}}</div>
<div class="conversation-details">
<span class="unread-numbers"></span>
{{input type='checkbox' class='chk-conversation' checked=conv.isChecked}}
<span class="conversation-name">{{conv.customer.name}}</span>
<span class="phone-number">{{conv.customer.cellPhoneNumber}}</span>
<p class="conversation-text">{{conv.lastMessage}}</p>
</div>
</div>
</div>
{{/if}}
{{/each}}
This is the main problem in ember's rendering which is getting much better by time, Ember connects all your binding to your created models so it re-renders the view on every added model, and hence the delay.
And I've been in the same situation, you have a couple of solutions here
1- Using Ember.ListView
You can use Ember list-view which is an Ember plug-in that adds lazy rendering to a List of items, very useful if you have items that can be displayed in the same height in pixels.
2- Using Ember Cloaking
Ember Cloaking is about the same as list-view but has flexible heights, although you still need to compute them before rendering.
3- Using visibility checker like waypoints
I've done this myself and its a little tedious but plug-in free none the less
You create a variable in your component that is set to true when it's visible in the waypoint.
sample code, not a real one
export default Ember.Component.extend({
visible:false,
didInsertElement:function() {
var waypoint = new Waypoint({
element: this.$()[0],
handler: function(direction) {
this.set('visibile',true)
}.bind(this)
})
}
})
Then Move your content into this component
And then inside this component:
{{#if visibile}}
<div class="conversation-content-wrapper" {{action "clickConv" conv preventDefault=false}}>
<div class="history-message-assigned in-progress-closed" style="display:none;"><p><i class="icon-x"></i>Conversation closed</p></div>
<div class="history-message-assigned in-progress-assignation" style="display:none;"><p><i class="icon-assign"></i>Conversation assigned</p></div>
<div class="history-message-assigned in-progress-reopen" style="display:none;"><p><i class="icon-re-opened"></i>Conversation re-opened</p></div>
<div class={{conv.selectedClass}}>
<div class="conversation-time-history">{{{conv.status}}}</div>
<div class="conversation-details">
<span class="unread-numbers"></span>
{{input type='checkbox' class='chk-conversation' checked=conv.isChecked}}
<span class="conversation-name">{{conv.customer.name}}</span>
<span class="phone-number">{{conv.customer.cellPhoneNumber}}</span>
<p class="conversation-text">{{conv.lastMessage}}</p>
</div>
</div>
</div>
{{/if}}
and then the "for-each" block
{{#each conv in model itemController='singleconv'}}
{{the-component conv=conv}}
{{/each}}
Then use a counter or something to make the first 10 visible.
As I said this is only a simple example you can dig more into it.
Is there a way to do grouping in a polymer repeat template? I have a list of items with doc.name and doc.manualType, but I want to group a list of items so the manualType only displays once per group instead of for each item.
Or how do I update my binding to have a previousManualType so I can only display the manualType if it's different than the previous manualType.
<template id="docListTemplate" bind="{{searchResults}}">
<div class="vGroup">
<core-selector id="selector" class="list" multi selected="{{multiSelected}}">
<template repeat="{{doc, i in data}}" {previousManualType:''}>
<template if="{{doc.manualType!=previousManualType}}">
<h1>{{doc.manualType}}</h1>
</template>
<div class="cb item">
{{doc.name}}
</div>
</template>
</core-selector>
</div>
</template>
What about
<template id="docListTemplate" bind="{{searchResults}}">
<div class="vGroup">
<core-selector id="selector" class="list" multi selected="{{multiSelected}}">
<template repeat="{{manualType in ManualTypes}}">
<template repeat="{{doc, i in manualType.data}}">
<h1>{{doc.manualType}}</h1>
<div class="cb item">
{{doc.name}}
</div>
</template>
</core-selector>
</div>
</template>
You need to prepare the data structures accordingly.
As Gunter pointed out the data structure seems to be the keypoint.
If you have no control over the input, then you will need to transform it.
You could user underscore / lodash to groupBy
http://underscorejs.org/#groupBy
https://lodash.com/docs#groupBy
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.
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.