How can i access a element inside of a handlebars template? Im trying to access the #element-{{id}} inside the Handlebars Helper but im receiving a null on log.
JSBin example
<div class="container">
<div class="panel panel-default">
<script id="video-template" type="text/x-handlebars-template">
{{#each items}}
<div class="panel-heading">
<h3 class="panel-title">{{snippet.title}}</h3>
</div>
<div class="panel-body">
{{someFunction id}}
<div id="element-{{id}}"></div>
</div>
{{/each}}
</script>
</div>
</div>
<script>
Handlebars.registerHelper('someFunction', function(id) {
console.log(document.getElementById("element-"+id));
});
</script>
The problem is that i dont have the element on the DOM when the handlebar helper is called, so i used a timeout function for that...
setTimeout(function(){
var element = document.getElementById("element-"+id);
console.log(element);
},1000);
anyone know a better way?
Why are you concantenating the element and the id.. ?
Handlebars.registerHelper('someFunction', function(id) {
console.log(document.getElementById("element-"+id));
Try this instead:
var butter = document.getElementById("butter_id");
console.log("thisid:",butter);
Also try removing handlebars from your function.Register your helper and function seperately and then call the helper variables referencing the function("getElementById or getElementByName")
function getElementById(name,url){
if(!url)url = window.location.href;
name = name.replace(/[\[\]]/9,"\\$&");
var regex = new RegExp('[?&]' +name+'(=([^&#]*)|&|#|$|)'),
results = regex.exec(url);
if(!results) return null;
if(!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/9,""));
Then:
...your helper...
Handlebars.registerHelper('butter',(id) {
var element = document.getElementById("butter_id");
console.log(document.getElementById("yourelement-",element));
Related
I am using bootstrap and need to conditionally start a <div class="row"> depending on the index of the item; in this case, each row has two items.
{{#each items as |item index|}}
{{#if item.isStartRow}}
<div class="row">
{{/if}}
...my code here
{{#if item.isEndRow}}
</div>
{{/if}}
{{/each}}
The trouble is that the HTMLBars validates the div has a starting and ending tag, therefore the above will not work. Can anyone suggest a workaround?
The end result would look something like this if there were 6 items in the array:
<div class="row">
<div class="col-md-6">Item 1...</div>
<div class="col-md-6">Item 2...</div>
</div>
<div class="row">
<div class="col-md-6">Item 3...</div>
<div class="col-md-6">Item 4...</div>
</div>
<div class="row">
<div class="col-md-6">Item 5...</div>
<div class="col-md-6">Item 6...</div>
</div>
It's turned out to be a different scenario once you've updated the question, and this is how I'd approach this
<script type="text/x-handlebars" data-template-name="components/item-row">
{{#each chunks as |chunk|}}
<div class="row">
{{#each chunk as |item|}}
<div class="col-md-6">{{item}}</div>
{{/each}}
</div>
{{/each}}
</script>
JS Component class
App.ItemRowComponent = Ember.Component.extend({
chunks : function(){
var items = this.get('rows.[]').slice(0); // make a copy
var count = Math.ceil(items.get('length')/2);
var chunks = [];
for(var i = 0 ; i < count ; i++){
chunks.push(items.splice(0,2));
}
return chunks;
}.property('rows.[]')
});
DEMO
You are free to customize child element if you make it as another component. It's an added flexibility.
To learn Ember, I've been trying to make a simple app that computes timezones.
When a person enters their city, and the other person's city, I make a GET request to my API, which returns the dates like so --
great_times: [array]
good_for_me: [array]
good_for_them: [array]
In handlebars, I have
<div class="container">
<div class="col-md-6 col-md-offset-3">
<header>
<h2>We found <span class="twenty-four-header">{{totalTimes}}</span>
great meeting {{pluralize totalTimes 'time' 'times'}} for you!</h2>
</header>
<div class="main-content">
<div class="row">
<div class="col-md-6">
<div class="form-group">
{{view RightTime.AutoCompleteAddressView value=myCity placeholder="What's your city?"
class="form-control input-lg" latLng=myLatLng}}
</div>
</div>
<div class="col-md-6">
<div class="form-group">
{{view RightTime.AutoCompleteAddressView value=theirCity placeholder="What their city?"
class="form-control input-lg" latLng=theirLatLng}}
</div>
</div>
</div>
{{#each meetingTime in greatTimes}}
{{render 'meetingTime' meetingTime }}
{{/each}}
</div><!--main-content-->
</div>
</div>
This works, but what happens is that when I update the city, It no longer updates this each loop.
I do know however that the model was updated, because the {{totalTimes}} computed property does update.
This is what my meeting Object looks like:
RightTime.Meeting = Ember.Object.extend({
meetingTimes: null,
myCity: null,
theirCity: null,
myLatLng: null,
theirLatLng: null,
totalTimes: function() {
if (this.meetingTimes) {
return this.meetingTimes.great_times.length;
}
}.property('meetingTimes'),
locationsData: function() {
return {
myLatLng: [this.myLatLng.k, this.myLatLng.A],
theirLatLng: [this.theirLatLng.k, this.theirLatLng.A]
}
}.property('myLatLng', 'theirLatLng'),
findTimes: function() {
var meeting = this;
if (this.myLatLng && this.theirLatLng) {
$.ajax({
url: 'api/meetings',
type: 'GET',
data: meeting.get('locationsData')
}).done(function(response){
meeting.set('meetingTimes', Ember.A(response));
});
}
}.property('myLatLng', 'theirLatLng')
});
I have a feeling that the problem lies in
.done(function(response){
meeting.set('meetingTimes', Ember.A(response));
});
I'm resetting the whole meetingtimes array, which may be the wrong way to go about it.
How would you go about making the meetingTimes arrray update and reflect in handlebars?
I'd probably just move great_times into a computed property that depends on meetingTimes and isn't chained.
something like
greatTimes: function() {
return Em.get(this, 'meetingTimes.great_times') || [];
}.property('meetingTimes'),
With a template like this
{{#each meetingTime in greatTimes}}
{{render 'meetingTime' meetingTime }}
{{/each}}
Considering the following:
Parent template:
{{view App.SomeView id="42" panelClass="default"}}
View template:
<div class="col-md-3 col-sm-6">
<div class="panel panel-{{panelClass}}">
<div class="panel-heading">
<h3 class="panel-title">
{{name}}
</h3>
</div>
<div class="panel-body">
{{description}}
</div>
</div>
</div>
View JS:
App.SomeView = Ember.View.extend({
templateName: 'views/some-view'
});
How can I achieve output HTML where the panel class gets set properly? At the moment it doesn't work because it wants to bind, so it inserts the ember metamorph script tags, instead of just plain text for the panel class.
Also, the template is wrapped in an extra div. How would I modify it so that the ember-view wrapping div is actually the first div in the template (the one with col-md-3 col-sm-6)?
The bind-attr helper exists for that reason. Here's the guide entry.
<div {{bind-attr class=":panel panelClass"}}></div>
Also, not sure if you can use a prefix on panelClass in the template. If might be easier just to use a computed property to add the panel- beforehand.
I'm sorry, I didn't see your second question about the extra div. The guide explains here how to extend the element.
App.SomeView = Ember.View.extend({
classNames: ['col-md-3', 'col-sm-6']
});
I'm using the jquery plugin scrollTo to create buttons to 'jump' to particular items in a long list. I bet there is a way to loop through each item and bind the event to it's corresponding button, but I don't know how to approach that. Sounds like something that would occur in the view though...
How can I bind a jQuery event to each 'item' rendered in the ember template below?
Ember 'items' template
<div class="buttons">
{{#each}}<a href="#" {{bindAttr class="isActive slug"}}></a>{{/each}}
</div>
<section class='region region-main-upper clearfix items'>
{{#each}}
<div {{bindAttr class=":postcard-left :item isActive slug"}}>
<div><img class='img-polaroid' {{bind-attr src=image}}></div>
<div>
<h4>{{title}}</h4>
<div class="span2">
<span class="item-property clear-row">Cost: {{printUSD itemCost}}</span>
<span class="item-property clear-row">Percent: {{percentVec}}%</span>
</div>
{{render 'options' options}}
</div>
</div>
{{/each}}
</section>
Straight javascript
This works, but is undesirable:
(function($){
$(document).ready(function() {
// this does what I am trying to achive, but is not maintainable...
$( "body" ).on( "click", ".solar", function(e) {
$('.items').stop().scrollTo( '.item.solar', 800 );
e.preventDefault();
});
$( "body" ).on( "click", ".coal", function(e) {
$('.items').stop().scrollTo( '.item.coal', 800 );
e.preventDefault();
});
});
})(jQuery);
I want to be able to only display a sidebar on some of my routes. How can I achieve something like this:
<div class="container">
<div id="ember-app">
<script type="text/x-handlebars">
// if currentRoute == /something, then show this:
<div class="row">
{{partial sidebar}}
<div class="span9 offset3 user-feed">
{{outlet}}
</div>
</div>
// else, show this:
{{outlet}}
// endif
</script>
</div>
</div>
<script type="text/x-handlebars" data-template-name="_sidebar">
// Sidebar code here ...
</script>
So when I visit /#/something I should see the sidebar, but on all other routes, I shouldn't.
You can observe the currentPath property to match the current route with Regex.
App.ApplicationController = Ember.Controller.extend({
showSidebar: function(){
var routes_array = ['two','four'],
currentPath = this.get('currentPath'),
filteredArray, showSideBar = false;
routes_array.forEach(function(itm){
var tab = new RegExp('^'+itm+'*');
if(!Em.isEmpty(currentPath.match(tab)))
showSideBar = true;
});
return showSideBar;
}.property('currentPath')
});
Just a simple try Here
A simple fix may be to use the partials argument with quotes?
{{partial 'sidebar'}}