I want to wrap some text in block. Cannot figure out how to do it.
JS:
Handlebars.registerHelper('mywrap', function (options) {
return '<p class="TEST" >' + options.fn(this) + '</p>';
});
Template:
{{#mywrap}}
This text must be wrapped
{{/mywrap}}
Final html should be like this:
<p class="TEST">This text must be wrapped</p>
Ember v1.0.0-pre4,
Handlebars 1.0.rc.2,
Jquery 1.9.0
There are lots of ways of wrapping text in a block, really depends on your usecase.
I'm assuming for some reason, literally writing the HTML is not what you're looking for.
Firstly, you can just return a Handlebars SafeString, however this presents a security issue if you are wrapping user-provided content.
Ember.Handlebars.registerHelper('mywrap', function (options) {
return new Handlebars.SafeString('<p class="TEST" >' + options.fn(this) + '</p>';)
});
Secondly, you can wrap it in a view
{{#view classNames="TEST" tagName="p"}}
This text must be wrapped
{{/view}}
Thirdly, you can create a handlebars helper that creates a view.
Ember.Handlebars.registerHelper('mywrap', function (options) {
var view = Ember.View.extend({tagName:"p",classNames:"TEST"})
return Ember.Handlebars.helper.view.call(this, view, options)
});
Caveat, I haven't actually checked the code so there may be typos
Related
How can I can concatenate strings( or how to add classes ) on templates on EmberJs?
ex.
<script type="text/x-handlebars">
// This div I want to add a class go, Is this the right way to do it?
<div class="fly {{isGo}}">Fly now</div>
// Or it's something like this?
<div class="fly "{{isGo}} >Fly now</div>
</script>
bind-attr used to be a good way of working around a limitation within Ember's rendering. Now with HTMLbars Ember has recommend that we move away from bind-attr as we have more powerful methods.
Ember 1.13 deprecated bind-attr in favor of the new syntax.
http://emberjs.com/deprecations/v1.x/#toc_bind-attr
Working example of the two proposed methods can be seen in action on ember twiddle ,here:
https://ember-twiddle.com/38f69f01d2fd994af3b0965f10882005?openFiles=templates.application.hbs%2C
Method 1
If you want to do the combination inside your handlebars template you could do something like:
<div class={{concat "fly " isGo}}>Fly now</div>
Method 2
otherwise use a computed property like:
flyingClass: Ember.computed('isGo', function() {
// return a string with 'fly' and the value of
// isGo. Will be updated if isGo changes.
// Array values are created with space delimited by
// ['className', 'anotherClassName', 'lastClastName'].join(' ');
// => "className anotherClassName lastClassName"
let going = this.get('isGo') ? 'going' : ''
return ['fly', going].join(' ');
})
and then in your handlebars template:
<div class={{flyingClass}}>Fly now</div>
The main difference between the two methods depends on how you want your separation of concerns. Right now it might be easier to just do Method 1, but as conditions get more complicated you could hide more of the work in the computed property.
There is a complete discussion of this in the Ember guide: http://emberjs.com/guides/templates/binding-element-class-names/
But you'd do it like this:
<div {{bind-attr class="isGo"}}>Fly now</div>
And in your controller:
App.MyController = Ember.ObjectController.extend({
flightIsAGo: true,
isGo: function() {
return "fly"+this.get('flightIsAGo') ? ' isGo' : '';
}.property('flightIsAGo')
}
I am using ember version 1.6.1. I would like to show an error message if user doest not enter username and password correctly. I think i have to use bind-style. now I have code like this:
<fieldset class="error-message" {{bind-style visibility="isVisible:visible:hidden"}}>
<span>invalid username/password</span>
</fieldset>
what is the best way to do it ?
Ember Handlebars supports dynamic class binding exceptionally better than it does style binding. To do that you'd bind-attr to the class. http://emberjs.com/guides/templates/binding-element-class-names/
Css
.visible{
visibility:visible;
}
.hidden{
visibility:hidden;
}
Handlebars
<fieldset {{bind-attr class=":error-message isVisible:visible:hidden"}}>
<span>invalid username/password</span>
</fieldset>
Example: http://emberjs.jsbin.com/didax/1/edit
You can bind-attr the style property and create a computed property that returns the raw style text visibility:visible, but that's ugly and not necessary in this situation.
Although class is generally the best way to set these visual changes, consider using classNameBindings instead of bind-attr. That would require you to create a View class.
However, the best way to bind element attributes that don't have a specific binding mechanism, would be via attributeBindings:
(this approach also needs a View class)
App.IndexView = Ember.View.extend({
attributeBindings: ['style'],
style: function() {
return 'color: #F00';
}.property()
});
This is way is a little better because you can watch the style property of your view class and it will automatically bind to your view markup. And since that is a computed property, you can create your own code to determine changes of other attributes in your view that could cause the style attribute to be reconstructed, and again, automatically bound to your view.
You could have a property that the style property watches with property('dependency'), so when it changes, style is once again computed and the view is updated. For example, let's say that you have a view which is a custom input box with built-in validation. You have a property valid which returns boolean, being true for valid and false for invalid values.
App.IndexView = Ember.View.extend({
attributeBindings: ['style'],
valid: function() {
return false;
}.property(),
style: function() {
// these variables and all should ideally be somewhere else,
// as color codes could potentially be global for the app
var _invalidColor = "#F00";
var _validColor= "#000";
if (this.get('valid')) {
return 'color: ' + _validColor + ';';
} else {
return 'color: ' + _invalidColor + ';';
}
}.property('valid')
});
(see jsbin)
Keep in mind this is a crude example to show the functionality/possibilities. Manually change the return value of valid property of the IndexView in JS Bin to see how it affects the view template.
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.
I'm trying to write a custom Ember handlebars helper that will return some HTML, but I can't access the block contents within the helper.
Template:
{{#link}}
This is the block content
{{/link}}
Helper:
Ember.Handlebars.registerHelper('link', function (options) {
var result = '<a href="http://example.com/">'
+ options.fn(this)
+ '</a>';
return new Handlebars.SafeString(result);
});
The result I'm expecting is: This is the block content
Instead I get: This is the block content undefined
Fiddle: http://jsfiddle.net/NQKvy/676/
What am I doing wrong?
I'm not sure it is currently possible to use block helpers in Ember.Handlebars easily. However, you could use a 'regular' Handlebars helpers like so:
{{link "This is the block content" url="http://www.example.com"}}
Helper:
Ember.Handlebars.registerHelper('link', function (value, options) {
var result = '<a href="'+options.hash.url+'">'
+ value
+ '</a>';
return new Handlebars.SafeString(result);
});
See this jsFiddle.
#chopper had the correct answer on how to do what it is you are looking for. However, I just wanted to touch on the issue of Block Helpers to clear up their meaning.
Block helpers are used to determine rendering patterns of a block. They are not "wrapping" helpers.
For example, a Block Helper you're undoubtedly familiar with is a simple {{#if}} helper. This helper intakes a conditional, and uses that to either output the information contained within it, or not. But it doesn't append information before/after the blocked section.
A more complex block helper would be the {{#each}} helper. The each helper will iterate through a set and, by repeatedly calling options.fn(arrayItem), it will render the block multiple times, on each iteration inputting new data into the designated handlebar tags. But those tags are necessary in order to input information.
How to use action helper in a i18n key. For example, the i18n key is
Please <a{{action displayList}}>click here</a> to display the list.
How to translate this properly with ember runtime(i.e handlebars uncompiled version)
It is been a while since this question was asked, but since I haven't found the solution anywhere, let me put my solution here. The way I solved it is using Handlebars subexpressions. For your example it would look like this:
in translation file
var translations = {
'fb.clickhere.msg': 'Please <a {{actionDisplayList}}>click here</a> to display the list.'
}
in Handlebars template
{{t 'fb.clickhere.msg' actionDisplayList=(action "displayList") }}
If Handlebar helpers support returning Ember.View instance then the following defined helper should work
{{localizedView fb.clickhere.msg}}
Handlebars.registerBoundHelper("localizedView", function(value, options){
// value = fb.clickhere.msg
var localizedString = loc(value); // localizedString = "<a{{action displayList}}>click here</a>"
return Ember.View.create({template: Ember.Handlebars.compile(localizedString)});
}) // Ofcourse you should define it before you can use this