Ember: How do I find handlebars partial in the directory? - ember.js

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.");
});

Related

Custom Handlebars block helper

How do I define a custom block helper in Handlebars (for use with Ember.js)? I've tried using the method described on the Handlebars site, but it doesn't seem to work. I get this error from Ember.js:
Assertion failed: registerBoundHelper-generated helpers do not support use with Handlebars blocks.
Here's the code for my helper. The idea is that the block will only be rendered if the models that I pass in are the same:
Ember.Handlebars.helper 'sameModel', (model1, model2, options) ->
if model1 is model2
new Handlebars.SafeString(options.fn(this))
else
''
6 months later, it looks like this is possible now, at least to a certain extent. You can view the discussion here. I agree with the pull request that this should usually be handled using computed properties, but this is still very useful in some cases.
I'm going to accept this answer to keep this post updated. If I've broken any SO etiquette, let me know. :)
Assertion is correct. You cannot do that, at least not it RC6 and before.
You may want to create a view with a template and bind some properties to it:
some.hbs
{{#if model1}}
This is model1 {{model1.name}}
{{/if}}
{{#if model2}}
This is model2 {{model2.name}}
{{/if}}
views/some.js
App.SomeView = Ember.View.Extend({
templateName: "some"
})
different template
<h3>{{view App.SomeView model1Binding=someModel1 model2Binding=someModel2}}</h3>

With Ember.js handlebars templates, how can I link to the full url of an object to force a model reload?

I currently have this template
{{#each model}}
{{#linkTo object this}}{{name}}{{/linkTo}}
{{/each}}
which creates
<a href="path/#/objectid"/>
This does not cause a model reload, but a page refresh with that url does.
How can I make a link in my template with a full url?
<a href="path/objects/{{id}}">{{name}}</>
does not work, because {{id}} does not seem to fully resolve inside the quotation marks, so I get something like:
path/objects/<script id="metamorph-5-start....
I have seen answers hinting at adjusting setupController, but what if I do not want to reload the model every time? It would be nice to have control over this from the templating side, i.e. using {{#linkTo}} when no reload is needed and some other trick when a reload is needed. Is there an easy way to create a full url based on model parameters in handlebars?
This is may not be a full solution to your problem, but as for this part:
does not work, because {{id}} does not seem to fully resolve inside the quotation marks, so I get something like:
there is help:
<a href="path/objects/{{unbound id}}">{{name}}</>
Using unbound does not put the script metamorph tag's around the property.
Hope it helps you to tackle down your problem.
I figured it out - although without changing the url, so I am still using a normal {{#linkTo...}}.
As mentioned in How to reload an ember data record?, record.reload() can be used - it works for me like this:
App.ObjectRoute = Ember.Route.extend({
...
setupController: function(controller, model) {
var record = App.Object.find(model.id);
record.reload();
controller.set("model", record);
},
});
If there was an easy alternative using a modified url, I would still be interested in finding out.

{{outlet}}, {{view}}, {{render}}, and {{control}} helpers

I am trying to put together a simple master-details Ember app. Directory tree on one side and file list on another.
Ember offers few helpers to render context into a view. Which of them I can use for:
Subtrees of the directory tree.
Details list.
In fact, would be very helpful if someone can point me to any docs I can read about the difference between {{render view}}, {{view view}} and {{control view}} helpers and how to use them properly.
Thanks a lot!
{{view "directory"}} renders the view within the context of the current controller.
{{render "directory"}} renders the view App.DirectoryView with template directory within the context of the singleton App.DirectoryController
{{control directory}} behaves the same way as render only it creates a new instance of App.DirectoryController every time it renders (unlike render which uses the same controller instance every time).
Update 18 Feb 2014: {{control}} has been removed.
The last two helpers are relatively new, so there isn't much documentation about them. You can find {{view}} documentation here.
Now looking at your use case, I don't think you need any of these helpers. Just use nested routes and the {{outlet}} helper and it should just work.
App.Router.map(function(){
this.resource('directories', function() {
this.resource('directory', { path: '/:directory_id'}, function() {
this.route('files');
});
});
});
You can build on that following this guide.
UPDATE: {{render}} now creates a new instance every time if you pass a model.
For a very good explanation of the helpers render, partial, outlet and template have a look at this question.
Just as a rough a summary, how one might use those helpers:
{{render "navigation"}} -> Renders the NavigationController and NavigationView at this place. This is helper is good for places, where the Controller and View do not change, e.g. a navigation.
{{outlet "detailsOutlet"}} -> This will provide a stub/hook/point into which you can render Components(Controller + View). One would use this with the render method of routes. In your case you will likely have a details route which could look like this. This would render the DetailsController with DetailsView into the outlet 'detailsOutlet' of the index template.
App.DetailsRoute = Ember.Route.extend({
renderTemplate: function() {
this.render('details', { // the template/view to render -> results in App.DetailsView
into: 'index', // the template to render into -> where the outlet is defined
outlet: 'detailsOutlet', // the name of the outlet in that template -> see above
});
}
});
{{view App.DetailsView}} -> This will render the given view, while preserving the current context/controller. One might change the context, e.g. using your master entity and pass its details to a view like this:
{{view App.DetailsView contextBinding="masterEntity.details"}}
This is helper is useful, when you want to encapsulate certain parts of a component in subviews, that have own custom logic like handling of actions/events.
{{control}} I know that control instantiates a new controller every time it is used, but I cannot see a good fit for your, nor have i a good example for using it.
To Understand the difference between ember {{render}},{{template}},{{view}},{{control}}
you can refer this article
http://darthdeus.github.io/blog/2013/02/10/render-control-partial-view/

emberjs template compile doesn't work in rc1

I have
Esploreo.TE.Views.ItemView = Ember.View.extend({
elementId : "item",
templateName : 'itemTemplate'
});
and a template like
<script type="text/x-handlebars" data-template-name="itemTemplate">
content of templat
</script>
and all works good. But i don't to want to use this type of coding. In previous Ember versions it was possible to write the template code in the definition of view, like this:
Esploreo.TE.Views.ItemView = Ember.View.extend({
elementId : "item",
template: Em.Handlebars.compile('content of template'),
});
but it doesn't work (emberjs 1.0.0-RC.1). This features is removed from this release?
That's a curious way of working with Ember! To answer your question though, you need to add .append() to the end of your .create() like so:
App.ItemView.create().append();
Obligatory jsFiddle: http://jsfiddle.net/MGXDe/
Whilst I don't know your use case for this, I can't stress enough that this seems a little too curious, bordering on bad usage of Ember.

How do I setup an Ember View class to be appended to a particular container?

Ember.View has a nice method called .appendTo("#container") which would allow me to specify a container div for the view. However, when I use the router and .connectOutlet method, an instance of my view is created automatically based on convention and is added to the page body element by default. Is there a way to configure the class definition of the view so that upon creation it will be inside my desired #container. Here is my view:
Jimux.BuildsView = Em.View.extend({
templateName: 'builds',
appendTo: '#jimux-header', #this was just a guess and did not work. but does some propery like this exist for the view?
tagName: 'div',
listVisible: true,
...
Another way to ask this question is: how do I tell Ember router to append a view to a particular item in the dom? By default the router appends the view to the body.
And here is the router bit:
# Connect builds controller to builds view
router.get('applicationController').connectOutlet("builds","builds", Jimux.buildsController)
To clarify, I dont want to put my whole Ember app in a container. I have several views in my application, and most of them are fine directly in the body. But there are a couple like the one mentioned in this question, which I want to put inside "#application-header" div.
You can specify the root element for your application object.
window.App = Ember.Application.create({
rootElement: '#ember-app'
});
Edit:
Having re-read your question, I think you should look into named outlets, so you could do something like:
<div id="application-header">
{{outlet builds}}
</div>
{{outlet}}
well..after understanding your question, i remember having same trouble. Also, thing is i didn't find any way to do this even after going through the Ember code. But later i understood that its for good purpose only. I know you already might have come across with handlebars with which we can acheive this. If we give a view a ID to get appended, we are constraining the application and the whole use of ember becomes useless. Ok coming to you question, as far as i know, we can acheive that appending mustache templates in you div element of HTML.
<div id="jimux-header">
{{view Jimux.BuildsView}}
</div>
This way we can use the Jimux.BuildsView where ever you want and as many times possible. The Beauty of Ember you have to say...
Just add rootElement in the application object.
var App = Ember.Application.create({
rootElement: '#container'
});