Get contents of Meteor template - templates

I have the following Meteor template:
<template name="homeBoxTpl">
<div>
Some content
</div>
</template>
I have an event binding so that when a button on the page is clicked it should get the html contents of the template "homeBoxTpl" - how can this be achieved?

What you need is an event handler, and like Chase say you can access the content of meteor templates using jquery, but meteor has its own way. In order to get a copy of the html, you can place a wrapper round the content in the template, then do this:
Template.homeBoxTpl.events({
'click #someButton':function(e,t){
var templateContents = t.$('.wrapperInTemplate').html();
}
})
Here we are using Template.$ wich returns a jQuery object of those same elements.
Take a look into Template.instances for more information

Just to clarify, where is the button? Is it in another template? I assume you only render homeBoxTpl once.
In which case the event handler for the template where your button exists will have no reference to another template instance. There is no global lookup where you can find all rendered instances of a specific Template
You will have to set an unique identifier "id" for it, or some other discerning info such as a class/attribute and find it via old fashioned JS DOM selectors/traversal.
document.getElementById is fastest, but if there are multiple instances of that template, t.firstNode does give you a good starting point for the DOM traversal.
However making your code dependent on a specific DOM layout is bad practice / too much coupling. Is there any reason why the data underlying that Template's HTML content isn't available somewhere else like a session or collection? It would perhaps be more flexible too to access the data not the HTML.

You can use jquery to access what you need. For example, if you have the following template:
<template name="homeBoxTpl">
<div class="content-container">
Some content
</div>
<button id="btn" type="button">Click me</button>
</template>
Then use the following javascript:
Template.homeBoxTpl.events({
'click #btn': function(e) {
e.preventDefault();
var content = $(".content-container").text();
console.log(content); //Result is "Some content"
}
});

Related

Rendering views based on dynamic content in Ember.js Handlebars?

Is it possible to dynamically render content in ember directly from the template?
i.e., using 4 links that are bound to 4 different template names:
v1
v2
v3
v4
{{render view.view_to_render generic_controller}}
or are there more efficient ways to achieve this?
From the original post, I guess that you would like to render dynamically an actual view, rather than a partial template.
The snippet
{{render view.view_to_render generic_controller}}
does not work (in my experience), because ember tries to look for a view named 'view.view_to_render', rather than interpreting it as a variable to read the view from.
The solution I use is to have a custom helper:
Ember.Handlebars.registerBoundHelper( 'renderBoundView', function ( panel ) {
var args = Array.prototype.slice.call(arguments, 1)
Array.prototype.splice.call(args, 0,0,panel.view, 'panel.model')
// Call the render helper
return Ember.Handlebars.helpers.render.apply(this, args)
})
This helper extracts the view name from the variable 'view' in the passed object, and then passes that name to the standard render helper. Then using
{{renderBoundView panel}}
where panel has properties 'view' with the name of the view and 'model' containing the (resolved) model does the trick.
Of course you could also interpret the object passed as a variable name to get from the current context (which is also one of the arguments passed to the helper).
The entire purpose of Ember is to dynamically render content.
If you want to render particular "views" that are driven from data, that's pretty easy in Ember. Ember calls these partial templates "partials", appropriately-enough :)
Say you have an attribute called partialToRender set in your controller for the template that you're doing your "generic rendering" on. Say it's bound to a set of buttons which are bound to actions which each change the value of partialToRender. Something like this:
<button {{action changePartialToRender 'hello'}}>Change to Hello</button>
<button {{action changePartialToRender 'goodbye'}}>Change to Goodbye</button>
<button {{action changePartialToRender 'yes'}}>Change to Yes</button>
<button {{action changePartialToRender 'no'}}>Change to No</button>
and then in your controller you'd have an action something like this:
App.IndexController = Em.ObjectController.extend({
partialToRender: null,
actions: [
changePartialToRender: function(newValue) {
this.set('partialToRender', newValue);
}
]
});
That'd mean whenever the user clicked on one of your buttons, the value of partialToRender would be changing. Sweet, right? :)
So now all that we need to do is hook up our bit of template code that renders the partial. A partial is just another template, but it's part of a page rather than a full one... some bit of different content in each case, to render into our initial template...
So, we revisit the template like this:
<button {{action changePartialToRender 'hello'}}>Change to Hello</button>
<button {{action changePartialToRender 'goodbye'}}>Change to Goodbye</button>
<button {{action changePartialToRender 'yes'}}>Change to Yes</button>
<button {{action changePartialToRender 'no'}}>Change to No</button>
{{#if partialToRender}}
{{partial partialToRender}}
{{/if}}
Note I'm just wrapping the partial in an if statement to make sure it doesn't render if it's not set.
Also note that I haven't specified the partials here for you. I've just kind of whet your appetite. If you're really interested in this, I suggest watching the Ember video on the getting started guide in the ember site. It's a bit rambling, but it shows off some of Ember's powerful features, or possibly go through the guides / tutorial over at the Ember main site.
Hope that answers your question :)

Calling an action within controller in Ember

I am getting some data from server and in my controller I am trying to display that in list format. What I want to do is to allow the user to click on any item of that list and call an action behind it. Here is my js code.
for(var index in posts) {
if (posts.hasOwnProperty(index)) {
console.log(1);
var attr = posts[index];
//console.log(attr);
/*$("ul#previous_recipients").append('<li class="list-group-item"><label>'+attr.name+'' +
'</label><a href="javascript:void(0)" class="close g-green" {{action "aa"}}>Add</a></li>');*/
$("ul#previous_recipients").append(Ember.Handlebars.compile('<li class="list-group-item"><label>{{attr.name}} </label>Add</li>'));
}
}
How to call action on it? {{action "test"}} is not being called.
You have to compile the handlebars template and define the test action inside actions hash in the same controller.
$("ul#previous_recipients").append(Ember.Handlebars.compile('
<li class="list-group-item"><label>{{attr.name}} </label>
Add</li>
'));
You have to move this html code from controller to a handlebars file,that will be good.
What you need to do is create an ember view and give it a
templateName
property which will contain your html and handlebars expression. Alternately, you could, inside the view say
defaultTemplate: Em.Handlebars.compile(/*your handlebars and html markup here*/)
using Jquery to do things like this is not the ember way of doing things.

How to create a DOM Element and use it in real time using Meteor and Templates

everybody.
I am using Meteor in a personal project and I could not do something very important to this project: I need to create some parts of the DOM in runtime and then populate them still in runtime, but using the Tamplates method I could not do this work. Maybe I am doing something wrong. Please, take a look in this example and say what's wrong or if there is a better way to do it.
Consider this example situation:
<template name = "exampleTemplate">
<div class="divToPopulate">
{{#each topModels}}
<div id="{{_id}}"></div>
{{/each}}
</div>
</template>
Then, in client.js I provide the data for topModels helper:
Template.exampleTemplate.topModels = function() {
return ExampleModel.find({},{limit:9});
}
When the Template is ready, I try to use those DOM elements in a javascript function called drawGraph(var domElementId) that is a Raphael.js function which draws a graph inside the DIV:
Template.exampleTemplate.rendered = function() {
var models = ExampleModel.find({},{limit:9});
models.forEach(function(model){
drawGraph(model._id);
});
}
But when I run this I get an error saying that the DOM element doesn't exist. So I was wondering if there is a better way to append an DOM element and populate it on the fly.
Thanks for any help.

Ember JS/Handlebars view helper

Currently, if we define our view as {{#view App.myView}}, ember/handlebars will wrap the view element inside a <div id="ember-1234" class='ember-view'>.
Is there a way to stop this?
You probably want to set tagName as ''.
App.MyView = Em.View.extend({
tagName: ''
});
At least it stops wrapping inner contents.
If you want to customize view element's id, you can use:
{{#view App.myView id="my-id"}}
I usually think my views as wrapper. For example, if the initial given html code is :
<div class="item"><p>my stuff></p></div>
Then I create a view with a tagName property as "div" (which is default), and classNames property as "item". This will render, with proper handlebars template :
{#view App.myView}
<p>my stuff></p>
{/view}
-> render as
<div id="ember-1234" class="ember-view item">
<p>my stuff></p>
</div>
Then if you need to have your proper ID on this div, you could define the "elementId" property on your view class (before create()). (#see source code)
I assume you are talking about the 'ember-view' class which is not customizable (element type being customizable thanks to the tagName attribute...).
Actually, Ember later uses this class to register (once!) an event listener on the document in order to dispatch events to the JS view.
I don't mind it would be that simpler to avoid using this class. There would have to find another way to select all ember's controlled element, but I have no idea how.
See source, # line 117.
If I understand you correctly you want to achieve something like jQuery's replaceWith? You can use this in Ember.js when my Pull Request gets merged: https://github.com/emberjs/ember.js/pull/574.
Also have a look at Create Ember View from a jQuery object

how can i unbind an emberjs handlebar helper

I have a custom handlebar helper:
Handlebars.registerHelper('foo', function(key) {
return (key + ' bar');
});
and in my html I have:
{{foo beer}}
the result is
<div id="ember127" class="ember-view">beer bar</div>
how can I make my own handlebar helper act like the ember {{unbound beer}} and just produce "beer bar" without any additional markup ?
So I think you might be confused on how the helpers, templates, and Ember views work exactly. The markup you created is expected and is the exact markup you'd get with a working unbound helper.
Ember.Handlebars templates are always placed within an Ember view object (as you have above). Something that a normal bound helper would produce would be:
<div id="ember127" class="ember-view">
<script id="metamorph-1-start" type="text/x-placeholder"></script>
beer bar
<script id="metamorph-1-end" type="text/x-placeholder"></script>
</div>
Now if you want to surround your string with some other tag than a div (lets say an anchor tag or something), then you'd need to create a view, set it's template and tag name, then append that view.
Take a look at this jsFiddle and take a look at the results pane in your inspector for some examples of what I'm talking about. Hope that clears things up for you.
Ember has a helper called unbound that lets you wrap another helper. You can thus turn your bound (automatically) foo helper into an unbound one like so
{{unbound foo beer}}