Defining a block helper with Handlebars - ember.js

I'd like to define a block helper that puts the text in the block into a tag. I used an example from http://handlebarsjs.com/block_helpers.html as a start but my code doesn't work. What do I have to change to get test as the output of this block helper?
app.js
App = Ember.Application.create();
Handlebars.registerHelper('link', function(options) {
var result = '' + options.fn(this) + '';
return Handlebars.SafeString(result);
});
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Example</title>
</head>
<body>
<script type="text/x-handlebars">
<p>
{{#link}}
test
{{/link}}
</p>
</script>
</body>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src="js/handlebars.js"></script>
<script type="text/javascript" src="js/ember.js"></script>
<script type="text/javascript" src="js/app.js"></script>
</html>

Just a couple of details (EDITED):
You just need to create a new instance of Handlebars.SafeString before returning it. Please check #muistooshort's jsfiddle here with a working example of what you are trying to achieve.
Block helpers are a little bit more complex and used when is needed to invoke a section of a template with a different context. If it is not your case, you could use the syntax for regular Handlebars helpers. (I'll leave the following code here for future reference, although it's not relevant in this case)
Declare helper in app.js:
Ember.Handlebars.registerHelper('link', function(value) {
var result = '' + value + '';
return new Handlebars.SafeString(result);
});
In index.html replace your current template with:
<script type="text/x-handlebars">
<p>
{{link test}}
</p>
</script>
Hope this helps!

Related

Ember - Missing helper action for HBS files

I have written a html with a div.
I have two hbs files. I rendered one as partial and other as normal. I am not able to invoke action on the templates. I am getting missing helper error.
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Ember Starter Kit</title>
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div id="holder">
</div>
<script src="js/libs/jquery-v1.11.1.js"></script>
<script src="js/libs/handlebars-v1.3.0.js"></script>
<script src="js/libs/ember-v1.6.1.js"></script>
<script src="js/libs/ember-data.js"></script>
<script src="js/app.js"></script>
</body>
</html>
JS:
var data={title: "My New Post", body: "This is my first post!"};
function getTemplate(templateName,hbsPath,type){
$.ajax({
url: hbsPath, //ex. js/templates/mytemplate.handlebars
cache: true
}).done(function (src) {
if (type === "partial") {
Handlebars.registerPartial(templateName, $(src).html());
} else {
template = Handlebars.compile($(src).html());
temp=template(data);
$("#holder").append(temp);
}
});
}
getTemplate("dummy","/Test/templates/dummy.hbs","partial");
getTemplate("dummy","/Test/templates/application.hbs");
App = Ember.Application.create({});
App.Router.map(function(){
this.resource('dummy');
});
App.ApplicationController=Ember.ObjectController.extend({
needs:['dummy'],
actions:{
refresh: function(){
alert("application template refresh");
}
}
});
App.DummyController=Ember.ObjectController.extend({
actions:{
refresh: function(){
alert("dummy template refresh");
}
}
});
HBS:
application.hbs:
<script id="application" type="text/x-handlebars-template">
{{> dummy}}
</script>
dummy.hbs:
<script type="text/x-handlebars" data-template-name='dummy'>
<div {{action 'refresh' target="controllers.dummy"}}>
Refresh
</div>
<div {{action 'refresh'}}>
Refresh
</div>
</script>
The code in ur demo and the code in question are different. Here is a fixed demo based on the code in ur question.
Fixing the demo u provide may need you to include the vanilla handlebars library as ember is now using HTMLBars which is built on top of handlebars but a bit different.
Em.Handlebars.compile is now actually using HTMLBars compile method. You can see here.
You may need to use something like https://github.com/rwjblue/broccoli-ember-inline-template-compiler

creating and adding new Ember View elements to the DOM in ember version 1.8

I have seen this work in previous versions of Ember but I cannot get it to work in version 1.8
I would like the addNewView method in the index controller to create and add new App.ReusableView with its designated template as an element to the DOM div. I have tried several combinations and none work with this ember version.
OR, am I approaching this wrong and have the template using an {{#each}} to read from a model and have the controller just add elements to the controller?
jsbin: http://jsbin.com/xidoqo/1/edit?html,js,console,output
error
Error: Assertion Failed: You cannot append to an existing Ember.View. Consider using Ember.ContainerView instead.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Playground Ember</title>
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" type="text/css" href="css/bootstrap-v3.1.1.min.css">
</head>
<body>
<script type="text/x-handlebars">
<h2>main page</h2>
{{outlet}}
</script>
<script type="text/x-handlebars" id="index">
<button {{action 'addNewView'}}>addNewView</button>
<div id='divHolderId'></div>
</script>
<script type='text/x-handlebars' data-template-name='reusable'>
my reusable view content
</script>
<script src="js/libs/jqueryv1.11.0.min.js"></script>
<script src="js/libs/bootstrapv3.1.1.min.js"></script>
<script src="js/libs/handlebars-v1.3.0.js"></script>
<script src="js/libs/ember-1.8.1.js"></script>
<script src="js/app.js"></script>
</body>
</html>
app.js
App = Ember.Application.create();
App.IndexController = Ember.Controller.extend({
actions: {
addNewView: function() {
console.log('addNewView called');
var view = App.ReusableView.create();
view.appendTo('#divHolderId'); // error:
}
}
});
App.ReusableView = Ember.View.extend({
templateName: 'reusable'
});
edit1: (also tried instantiating a ContainerView with the same error)
addNewView: function() {
console.log('addNewView called');
var container = Ember.ContainerView.create({
childViews: [App.ReusableView.create()]
});
container.appendTo('#divHolderId');
}
If you absolutely must use views, then this will work: http://jsbin.com/zufomiweqe/2/edit
It's a little strange, though, the Ember.ContainerView's API didn't really get too much love when it was implemented. One of the bad things is that any actions to be triggered on the ContainerView have to be triggered via view.parentView, since the child views don't directly have access to the ContainerView's context.
Try that out, though, I hope it works out for you :-)
Have you checked out components at all? What you're describing feels very much like the way that we did things in Ember before components existed, and it was all very unwieldy and error-prone.
I'm not sure about your specific use-case, but I would have an array that represents the contexts for your views, and clicking addNewView would simply push a context to the array. In your template:
{{#each thing in contexts}}
{{my-new-component thing}}
{{/each}}

Interleaved closing tag error in Handlebars (Ember.js)

I recently decided to try Ember.js.
I set up a small application, but I can't get something to work.
I have a file app.html
<!doctype>
<html>
<head>
...
</head>
<body>
<script type="text/x-handlebars">
...
</script>
</body>
</html>
Now, of course, this doesn't render anything. I include handlebars.js, ember.js, and app.js and now then everything renders properly.
The problem is that when I try to add something with curly braces, the output is blank. For example, if I set some variables in my JS files and want to display it in my app, like <h1>{{title}}</h1>, I get <h1></h1>. When I try to put {{input value="Username"}}, nothing gets displayed.
I get no error messages, except when I use closing tags. For example, this
{{#link-to "http://google.ca"}}Link{{/link-to}}
Will make my whole web page simply display
line 117: interleaved closing tag: link-to
I have no idea what is wrong. Even googling the error message doesn't help much.
Any hint?รง
UPDATE
This code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Ember Starter Kit</title>
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/normalize/2.1.0/normalize.css">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="http://builds.handlebarsjs.com.s3.amazonaws.com/handlebars-v1.3.0.js"></script>
<script src="http://builds.emberjs.com/tags/v1.8.0/ember.js"></script>
<script type="text/javascript">
App = Ember.Application.create();
App.Router.map(function() {
// put your routes here
});
App.IndexRoute = Ember.Route.extend({
model: function() {
return ['red', 'yellow', 'blue'];
}
});
</script>
</head>
<body>
<script type="text/x-handlebars">
<h2>Welcome to Ember.js</h2>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="index">
Link
<ul>
{{#each item in model}}
<li>{{item}}</li>
{{/each}}
</ul>
</script>
</body>
</html>
Renders a blank page with this error message:
line 36: interleaved closing tag: each
I'm not sure that's normal.
link-to is meant for ember routes only. (http://emberjs.com/guides/templates/links/)
In your case I would just write the html for the link in the template directly.
Here is a small sample ember.js app with the google.ca link, I have a feeling that your html may not be setup correctly with an outlet and a template:
http://emberjs.jsbin.com/qivunivabo/3/edit
I found the problem and this is really stupid.
My HTML files are delivered by a framework that uses Mustache as its template engine (server side) and therefore it renders all the {{something}} tags before sending the output to the broswer.
:/

Contents of a view not displaying, simple app based on TODO tutorial, ember.js

I'm trying to create a simple TODO app based on the one in the Getting Started Ember.js tutorials, but with persistence to a backend.
I've had everything working until I wanted to look at wrapping my markup for rendering a todo in a view (called 'todo-element'), to enable drag & drop sorting.
Then, my view refused to render. I've simplified the markup for the view just to render the text 'Hello', to try to debug things. The instance of the view sets the tagName to 'li'. So I should be getting a list of lis with the text 'Hello' in them. However, all I get is a list of empty lis.
This is the markup:
<!DOCTYPE html>
<html>
<head>
<title>Todos</title>
</head>
<body>
<script type="text/x-handlebars">
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="todos">
<section id="todos">
<header>
<h1>The TODOs</h1>
{{input type="text" placeholder="Enter new TODO description here ..."
value=newDescription action="createTodo"}}
<button {{action "createTodo"}} id="add-todo">Add</button>
</header>
<ul id="todos">
{{#each itemController="todo"}}
{{todo-element}}
{{/each}}
</ul>
</section>
</script>
<script type="text/x-handlebars" data-template-name="todo-element">
<span>Hello</span>
</script>
<script type="text/javascript" src="javascripts/jquery"></script>
<script type="text/javascript" src="javascripts/handlebars-1.0.0.js"></script>
<script type="text/javascript" src="javascripts/ember.js"></script>
<script type="text/javascript" src="javascripts/ember-data.js"></script>
<script type="text/javascript" src="javascripts/todos/app.js"></script>
<script type="text/javascript" src="javascripts/todos/todo.js"></script>
<script type="text/javascript" src="javascripts/todos/router.js"></script>
<script type="text/javascript" src="javascripts/todos/todos_controller.js"></script>
<script type="text/javascript" src="javascripts/todos/todo_controller.js"></script>
<script type="text/javascript" src="javascripts/todos/todo_element_view.js"></script>
<script type="text/javascript" src="javascripts/todos/edit_todo_view.js"></script>
</body>
</html>
And this is the code for the view:
Todos.TodoElementView = Ember.View.extend( {
templateView : 'todo-element',
tagName : 'li'
} );
Ember.Handlebars.helper( 'todo-element', Todos.TodoElementView );
My best guess is that the 'todo-element' markup is not getting associated with the TodoElementView, as I get exactly the same empty list of lis if I change the 'todo-element' markup's data-template-name to something random.
If anybody could help me with where I'm going wrong here, I'd be very grateful.
Cheers,
Doug.
think you are little confused between ember components and ember views
1. A view is called with view helper {{view App.ViewName}}. Your code {{todo-element}} looks more like a component.
In your component you have a static tag span hello so I guess it's showing only hello. Put dynamic data in it using {{}}

Handlebar block helper doesn't work as it should

I try to use the code from Defining a block helper with Handlebars to create a block helper. http://jsfiddle.net/6Jaya/ by #danii shows that it should work. But it doesn't. I get the following output:
Is this a bug or do I miss something?
app.js
App = Ember.Application.create();
Handlebars.registerHelper('link', function(options) {
var result = '<a href="http://www.example.com">'
+ options.fn(this)
+ '</a>';
console.log(result);
return new Handlebars.SafeString(result);
});
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Example</title>
</head>
<body>
<script type="text/x-handlebars">
<p>
{{#link}}
<img src="http://placekitten.com/50/50">
{{/link}}
</p>
</script>
</body>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src="js/handlebars.js"></script>
<script type="text/javascript" src="js/ember.js"></script>
<script type="text/javascript" src="js/app.js"></script>
</html>
Why don't you just use? Is there a specific reason for this?
Handlebars.registerHelper('link', function(value) {
var result = '<a href="http://www.example.com">'
+ value
+ '</a>';
console.log(result);
return new Handlebars.SafeString(result);
});