Confusion about "data-template-name" and "id" in "<script>" tag - ember.js

After <script type="text/x-handlebars"
a. I'm wondering in what cases do I put data-template-name and what cases do I put id.
In the guide tutorial video source they use ids exclusively.
In the todomvc source and pretty much everywhere else I've seen, data-template-name is used.
b. And what exactly is put after data-template-name and id (i.e. what comes after their =)?

a) AFAIK id is the newer version of data-template-name, and they seem to work the same.
b) The id allows you to identify a template it in your routing, rendering or 'views'.
For Routing:
You can use this name to help the router identify which template to render, e.g. use this.render('displayStuff) during the renderTemplate in a route, to "override" the default template that belongs to the route.
See also: http://emberjs.com/guides/routing/rendering-a-template/
For Rendering:
Templates allow specific ways to change rendering. Ember-Handlebars provides {{render}} and {{partial}} to change the default template associated to the view.
See also: http://emberjs.com/guides/templates/rendering-with-helpers/
For Views:
By default, a view will find its corresponding template based on convention. So the somethingView has an associated somethingController and a something template (so template with id='something'). A view will also allow to forgo this convention by setting its templateName parameter.
See also: http://emberjs.com/guides/views/inserting-views-in-templates/
hope it helps!

Both work and are correct but data-template-name has a higher precedence and gives you more freedom re: element id's (they wont conflict with template ids)
via http://discuss.emberjs.com/t/ember-components-id-or-data-template-name-in-handlebars-script-tag/3847
also when you move your handlebars templates to stand alone files (production situation lets say) you won't need to worry about id vs data-template-name (let your build tools do this for you based on the template file name)

Related

Code-completion support for Django template language in Pycharm

In the template files code-completion works well for html tags and for adding matching {%,
What I want is for eg: if I type blog. and Ctrl + Space, it should show me the options like blog_title,blog_author etc, that are associated with blog.
Is this possible at all?
I do not think it is possible as PyCharm has no knowledge of the type of objects you pass as context to the template. It could infer it from the view where the template is used but we are not there yet.
It is possible if you register your own template tags with explicit name in your code.
Example: register.tag ("page_attribute", PageAttribute)
See also: https://github.com/divio/django-cms/issues/3878 where the same thing came up.
PyCharm will recognize that and do as you asked.

Ember.js flat route structure vs. mess in root templates dir

Using flat route (if a view has to be displayed in a separate view) structure solves many problems and helps to avoid unnecessary code, but all templates in a root template dir are more than mess:
For example:
(using ember-rails)
AddressBook.Router.map () ->
#resource 'contacts'
#resource 'contact', path: '/contacts/:contact_id'
#resource 'contactNew', path: '/contacts/new'
#resource 'contactEdit', path: '/contacts/:contact_id/edit'
all templates for routes defined above have to be in the root directory. With more routes it'd be more than a problem to maintain it.
Is it possible to keep templates in order? Or maybe something has changed when it comes to Ember router?
I'm assuming that you're using some kind of Handlebars pre-compiler which is getting the template name from the path. (I've never used rails, so I don't know if that's built into Ember-rails.) If that's the case, I think you have two options.
You could attempt to modify/configure the pre-compiler so that it takes the template name from somewhere other than the path. I don't know which one you're using, so I can't really give you details.
You can change the template that the route renders. You could use the render method of Route, or you could defined the view for the route and change the layoutName property.
Personally, I would highly suggest taking advantage of nested routes, as they offer many other benefits besides template organization. But if you really don't want to, look up documentation on your pre-compiler and try option number 1. You might be able to come up with something clever.
EDIT: With Ember-Rails, option 1 is probably the best. I don't know anything about Ruby, but I'm pretty sure everything you need is in template.rb.

Is the "loading" template special in Ember.js?

I see that the following template is rendered if loading the model takes a long time:
<script type="text/x-handlebars" data-template-name="loading">
<h1>Loading</h1>
</script>
The Route must be defined:
App.LoadingRoute = Ember.Route.extend({});
But the router needs no configuration for this to be active. I think this is ember-related behavior (although it could also be handlebars-related, but I do not think so).
Are there other special template names?
Where is this magic documented? (not possible to find it in the Ember documentation)
As you already noticed the router needs no definition for the LoadingRoute since it's somewhat special. The LoadingRoute will be looked up by ember, and if it's find one it is used for exact the expected behavior.
Have a look at this jsbin for an simulated loading example.
Are there other special template names?
Yes, there is also a special route called FailureRoute which can be used to handle errors globally.
Where is this magic documented? (not possible to find it in the Ember documentation)
As for some documentation on this please see this gist. Some of the changes where introduced not long ago, so documentation is somewhat sparse.
Hope it helps.

Emberjs - unable to redefine named, explicitly compiled Handlebars template

As part of an attempt to port a fairly large/complex existing application to the Ember world, I'm generating and compiling named Handlebars templates dynamically, and associating views with them, using the technique:
var template = Ember.Handlebars.compile("some handlebars stuff");
Ember.TEMPLATES["myTemplate"] = template;
var view = Ember.View.create({
templateName: "myTemplate"
});
One of the things I'd like to do is be able to recompile new/different Handlebars template markup which overwrites the template named "myTemplate" and have it be accessible to views at that name.
I'm getting unexpected results trying to do this - a couple fiddles that illustrate the problems:
First fiddle - Shows what happens if you wait before rendering a view after the named template contents have changed.
Second fiddle - Shows what happens if there's no delay before rendering a view after the named template contents have changed.
There's obviously some magic under the hood that I'm not understanding. Can anyone shed some light on this?
UPDATE:
I went through the source code for Ember.View and the container module, and came to realize that I could solve the problem in the First fiddle by overriding the "template" computed property in a way that skips the container cache lookup. I've put up another fiddle here to demonstrate the solution I found.
This seems to be working the way I'd like it to - but - it feels like I might be fighting with the framework and "unhooking" from the container in a way that might bite me later. Is there a better, more Ember-esque way to accomplish what I'm trying to do? Will the hack I found break things?
UPDATE 2
I've also discovered that it's also possible to simply call
view2.get('container').reset();
before appending view2 in the First fiddle. Seems cleaner/safer, but is it "legal"? I've updated the First fiddle to illustrate this.
(in the second fiddle, both views show the second template)
This is because view1.appendTo($("#target")); just schedules the append, actual view rendering does not happen until end of the run loop. Before that happens, you've set Ember.TEMPLATES["myTemplate"] = template2;
(in the first fiddle, both views show the first template)
Pretty sure this is because ember container caches template fx, but not 100% on that. Checking...
I'm going to call this one answered. As I mentioned in my second comment, I'm using the solution shown in this fiddle in my project, along these lines:
mYiew.get('container').reset();
There's some discussion about the container not being intended to be used as an API here: https://github.com/emberjs/ember.js/commit/5becdc4467573f80a5c5dbb51d97c6b9239714a8 , but there doesn't seem to be any mention of using the container from Views for other use cases.
Also, a View's container can be accessed directly (at ".container") - meaning the devs haven't made it "hard" to get to the way they have for an Application's ".__ container __". This might suggest something about how they intend it to be used.
Since a View having the ability to clear its cache whenever it wants to doesn't seem to me to be unreasonable or a bad practice, I'm using the above mentioned solution...at least until someone sets me straight with a better idea (or a cache API).

jsRender template disappears after rendering

After I call render on my jsRender template, it seems to be consumed, and thus is removed from the DOM. This is frustrating as I have a page where the template needs to be rendered several times depending on user interaction.
console.log($('#tpl'));
$('#container').html($('#tpl').render(json));
console.log($('#tpl'));
The second console.log is an empty array, and I can confirm the template no longer exists using the DOM inspector and the exception that jsRender throws: Uncaught JsRender Error: Unknown template: "#tpl" -- the page must be reloaded to re-inject the template into the DOM.
How can I persist the jsRender template between renderings?
I'm still not sure why it has to be consumed and simply can't stay in the DOM after rendering the first time, but I found a workaround. If anybody knows the reason for removing the template from the DOM, I'm still interested.
Update: Actual answer (Thanks, Boris)
My template was within my #container element, so the html() method was of course overwriting it. Silly me.
Workaround Neat little trick anyway
Using this 'variant' example, I saved the template in a local variable. Then I call render on the variable name instead of the jQuery selector:
var tpl = $.templates('#tpl');
.
.
.
console.log(tpl);
$('#container').html(tpl.render(json));
console.log(tpl);
This has also managed to preserve the template across renderings.
I also had a similar problem today where I had two target divs and two script block templates in the body. My problem was that I hadn't closed the div element tags correctly (too much xaml) and the result was the second template was never rendered as it couldn't be found.
Here's a JsFiddle showing the correct usage (rather than the /> self-closing syntax):
http://jsfiddle.net/jgoldsmith/XvvPC/
Hope that helps someone else.