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
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 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 am playing around with Ember.js (within Rails app) and got the the point when displaying a form. I used "partial" handlebars tag, like this:
{{partial "entity_edit_fields"}}
Ember tries to retrieve the template from _entity_edit_fields.hbs file. However, I have put all templates related to entity into separate directory. Now, I'd like to tell Ember to look to entity/_edit_fields.hbs. How can I achieve this?
To include the template entity/_edit_fields.hbs as a partial use:
{{partial "entity/edit_fields"}}
If you get stuck on something like this again, try having a look at the ember test suite. There will almost always be an example there that can help answer your question. I wasn't sure how partial worked either, so before answering I had a look at handlebars_test.js
test("should render other slash-separated templates using the {{partial}} helper", function() {
Ember.TEMPLATES["child/_subTemplate"] = Ember.Handlebars.compile("sub-template");
view = Ember.View.create({
template: Ember.Handlebars.compile('This {{partial "child/subTemplate"}} is pretty great.')
});
Ember.run(function() {
view.appendTo('#qunit-fixture');
});
equal(Ember.$.trim(view.$().text()), "This sub-template is pretty great.");
});
I am wondering if there is a way to bind data attributes in a template when calling a view.
For example (this doesn't work):
{{ view App.SomeView data-dateBinding="currentDate" }}
I have ended up doing it this way:
<a {{bindAttr data-date="currentDate"}}></a>
There must be a way to do it when calling the view?
More on the excellent answer from #kurt-ruppel.
An example using : to describe the property for attribute binding, entirely done from the view.
App.SomeView = Ember.View.extend({
attributeBindings: ["date:data-date"],
date: function() { return '1642-12-06' }
.... rest of view
})
The cleaner template.
{{view App.SomeView}}
You have to define in App.SomeView which attributes you want put in the HTML.
App.SomeView = Ember.View.extend({
attributeBindings: ["data-date"]
.... rest of view
})
Now data-dateBinding should work:
{{view App.SomeView data-dateBinding="currentDate" }}
FWIW - and this is in response to #sly7_7's comments from the top answer -, it is possible to specify a data-* attribute binding in the view itself, as opposed to setting it in the template.
Similar to classNameBindings, you can prepend a preferred value to the attribute, joining the values with a ':'. Best place to see this in action is probably in the related ember.js tests. Gives credence to the value of good testing, seeing as how sometimes it serves as the best documentation.
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