Recursive template Ember/Handlebars - ember.js

For some reason, I can't call my helper in my template. It throws an error saying that my helper is undefined.
I've got the following code :
<script type="text/x-handlebars" id="catalog">
<div class="col-md-10">
<ul class="list-group">
{{#each catalog.catalog_categories}}
{{categoryHelper this}} // This works !!!
{{/each}}
</ul>
</div>
</script>
<script id="categories-template" data-template-name='test' type="text/x-handlebars-template">
<a data-toggle="collapse" href=".collapse{{ category.category_id }}" data-target=".child{{ category.category_id }}">
<li class="list-group-item">
{{ category.category_name_fr_sh }} // French name of category
</li>
</a>
{{#if category.category_children}}
{{#each category.category_children}}
{{categoryHelper this}} // This throw error saying that the helper is undefined
{{/each}}
{{/if}}
</script>
//app.js
Ember.Handlebars.helper('categoryHelper', function(category) {
var template = Handlebars.compile($('script#categories-template').html());
return new Handlebars.SafeString(template({category: category}));
});
EDIT:
Here's a jsfiddle
http://jsfiddle.net/CycS8/

When ember bootstrap, it will look for all templates with the selector script[type="text/x-handlebars"], script[type="text/x-raw-handlebars"], and for each template it will compile with the appropriate compiler engine:
Ember.Handlebars.compile for scripts with type="text/x-handlebars and Handlebars.compile for type="text/x-raw-handlebars.
After the compilation the script tag is removed from the dom.
Probally the $('script#categories-template').html() in your helper is returning nothing. Because the template isn't in the dom.
I think that the following could work:
templates
<script type="text/x-handlebars" id="catalog">
<div class="col-md-10">
<ul class="list-group">
{{#each catalog.catalog_categories}}
{{categoryHelper this}}
{{/each}}
</ul>
</div>
</script>
<script id="categories-template" type="text/x-raw-handlebars">
<a data-toggle="collapse" href=".collapse{{ category.category_id }}" data-target=".child{{ category.category_id }}">
<li class="list-group-item">
{{ category.category_name_fr_sh }} // French name of category
</li>
</a>
{{#each category.category_children}}
{{categoryHelper this}}
{{/each}}
</script>
app.js
Ember.Handlebars.helper('categoryHelper', function(category) {
var template = Ember.TEMPLATES['categories-template'];
return new Handlebars.SafeString(template({category: category}));
});
UPDATE
Ember provide the render view helper, I think that you can get this working using the following:
<script id="catalog" type="text/x-handlebars">
<div class="col-md-10">
<ul class="list-group">
{{#each catalog.catalog_categories}}
{{render "categories-template" this}}
{{/each}}
</ul>
</div>
</script>
<script id="categories-template" type="text/x-handlebars">
<a data-toggle="collapse" href=".collapse{{ category.category_id }}" data-target=".child{{ category.category_id }}">
<li class="list-group-item">
{{ category.category_name_fr_sh }} // French name of category
</li>
</a>
{{#each category.category_children}}
{{render "categories-template" this}}
{{/each}}
</script>

Your type is wrong, it should be type="text/x-handlebars" in your test template.

Related

Ember 2, ember-cli, render partial to only show categories title, but it doesn't work

I have normal, basic ember-cli project.
This is my application.hbs:
<div class="container-fluid">
<div class="row">
<div class="col-sm-3 col-md-2 sidebar">
{{render 'sidebar'}}
</div>
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
{{outlet}}
</div>
</div>
</div>
This is my post.hbs:
{{#each model as |post|}}
{{post.text}}
{{/each}}
This is my sidebar.hbs:
<ul class="nav nav-sidebar">
{{#each model.posts as |post|}}
<li>{{#link-to author}}{{post.author.name}}{{/link-to}}</li>
{{/each}}
</ul>
and everything else is standard.
How to make work {{render 'sidebar'}} with just the title of my categories?
Now it shows nothing.
Updated the answer above me.
// application.hbs
<div class="container-fluid">
<div class="row">
<div class="col-sm-3 col-md-2 sidebar">
{{side-bar}}
</div>
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
{{outlet}}
</div>
</div>
</div>
// templates/components/side-bar.hbs
<ul class="nav nav-sidebar">
{{#each posts as |post|}}
<li>{{#link-to author}}{{post.author.name}}{{/link-to}}</li>
{{/each}}
</ul>
// components/side-bar.js
// This triggers once the component is called out {{side-bar}}.
init: function() {
// You're extending ember component class here
// This class has its own init function if u dont call
// _super() it means that the component has not yet been
// Initialised and component's not working.
this._super();
// Use your queries or what ever u need here
// e.g query('posts', { user: 1 })
this.set('posts', this.get('store').find(x));
}
I'm not sure why the render helper was not deprecated in Ember 1.13 and removed in 2.0, but you really shouldn't use it any more. The render helper uses a view and a controller that is not at the top level. Views have been removed in 2.0, and controllers not at the top level are deprecated.
Make your sidebar a component.
// application.hbs
<div class="container-fluid">
<div class="row">
<div class="col-sm-3 col-md-2 sidebar">
{{side-bar model=model}}
</div>
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
{{outlet}}
</div>
</div>
</div>
// templates/components/side-bar.hbs
<ul class="nav nav-sidebar">
{{#each model.posts as |post|}}
<li>{{#link-to author}}{{post.author.name}}{{/link-to}}</li>
{{/each}}
</ul>

Ember.js navbar

This works fine:
<div class='collapse navbar-collapse' id='main-nav-collapse'>
<ul class='nav navbar-nav'>
{{#link-to 'index' tagName='li' activeClass='active'}}
{{#link-to 'index'}}Home{{/link-to}}
{{/link-to}}
</ul>
</div>
But when I add in another tab below, and restart the server nothing shows at all..
<div class='collapse navbar-collapse' id='main-nav-collapse'>
<ul class='nav navbar-nav'>
{{#link-to 'index' tagName='li' activeClass='active'}}
{{#link-to 'index'}}Home{{/link-to}}
{{/link-to}}
{{#link-to 'orders' tagName='li' activeClass='active'}}
{{#link-to 'orders'}}Orders{{/link-to}}
{{/link-to}}
</ul>
</div>
Orders is "orders.hbs" and is just a static html page.. and in my routers.js.coffee file is the following route:
Dashboard.Router.map ()->
#resource('orders')

Ember partials and actions

I have this issue trying to use an ember partial and an action that targets the view
...
<li class="buttonsList-item-horizontal btn btn-lg btn-secondary" {{action restore this target='view'}}>
<i class="fa fa-refresh"></i>
<span class="btn-text">Restore</span>
</li>
...
If I use this code inside a partial is not working if I use it directly in the template it works.
Any ideas or suggestions to accomplish the same result?
the template is
...
<ul class="list">
<li class="list-item list-item-separator">{{group.key}}</li>
{{#each content}}
{{partial 'templateElement'}}
{{/each}}
</ul>
...
Assuming you are talking about the view, and not the template which you called the view above you have the logic correct.
App.IndexView = Em.View.extend({
actions:{
blah:function(){
console.log('asdf');
}
}
});
<script type="text/x-handlebars" data-template-name="index">
<ul>
{{#each item in model}}
<li>{{partial 'foo'}}</li>
{{/each}}
</ul>
</script>
<script type="text/x-handlebars" data-template-name="foo">
<button {{action 'blah' target='view'}}>{{item}}</button>
</script>
http://emberjs.jsbin.com/hocanilu/1/edit

How to use tagName and Menu separator?

I am using tagName in my Ember template and a menu separator || but rendering is not quite what is expected. e.g Mouse pointer doesn't turn to Hand when pointing About or Home and || appears at the end of About. Where as Products appear alright. What is wrong?
<script type='text/x-handlebars' data-template-name='application'>
<div class='navbar navbar-default fixed-top'>
<div class='container'>
{{#link-to 'index' class='navbar-brand'}}Ember{{/link-to}}
<ul class='nav navbar-nav navbar-right'>
{{#link-to 'index' tagName='li'}}Home{{/link-to}}
||
{{#link-to 'about' tagName='li'}}About{{/link-to}}
<li>{{#link-to 'products'}}Products{{/link-to}}</li>
</ul>
</div>
</div>
<div class='container'>
{{outlet}}
</div>
</script>
You didn't wrap your menu items in <li>:
<ul class='nav navbar-nav navbar-right'>
<li>{{#link-to 'index' tagName='li'}}Home{{/link-to}}</li>
<li>||</li>
<li>{{#link-to 'about' tagName='li'}}About{{/link-to}}</li>
<li>{{#link-to 'products'}}Products{{/link-to}}</li>
</ul>

Unable to get the handlebar data into template

I am learning ember.js through the official documentation and am having the following html page that contains mustache template:
<section id="main">
<ul id="todo-list">
{{#each controller}}
<li {{bindAttr class="isCompleted:completed"}}>
<input type="checkbox" class="toggle">
<label>{{title}}</label><button class="destroy"></button>
</li>
{{/each}}
</ul>
<input type="checkbox" id="toggle-all">
</section>
However, the problem is that the browser displays the data as:
{{#each controller}}
{{title}}
{{/each}}
without rendering the seed data supplied into the template.
I am having the following javascript declarations just before the end of body tag:
<script src="js/libs/jquery.js"></script>
<script src="js/libs/handlebars.js"></script>
<script src="js/libs/ember.js"></script>
<script src="js/libs/ember-data.js"></script>
<script src="js/libs/application.js"></script>
<script src="js/libs/router.js"></script>
<script src="js/models/store.js"></script>
<script src="js/models/todo.js"></script>
The page loads without any error reported by firebug. Please let me know what I am missing.
I guess you are missing something fundamental - the handlebars script tag around your 'template', the data-template-name should be named depending on the route your are in, I've used here application only for the sake of the example. On the official guides you mentioned if you enable the html panel in embedded jsbin you will see what I mean, right under the body tag is the wrapping script tag named todos.
<script type="text/x-handlebars" data-template-name="application">
<section id="main">
<ul id="todo-list">
{{#each controller}}
<li {{bindAttr class="isCompleted:completed"}}>
<input type="checkbox" class="toggle">
<label>{{title}}</label><button class="destroy"></button>
</li>
{{/each}}
</ul>
<input type="checkbox" id="toggle-all">
</section>
</script>
Hope it helps.