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.
Related
I got the following error while developing our front-end with Ember.js:
ember Error: Compile Error: '...' is not a helper
What is the meaning of this error?
Reason
Ember throws this error if there is no component or helper with the given name is not found in your project or your dependent addons.
How to solve
You should check the name of the component or helper that you have written (possible errors are spelling errors or writing directory structure of the component incorrectly).
This twiddle shows example of this error message when the component my-component is called as {{my-component2 x=x}} instead of {{my-component x=x}} mistakenly.
This error can also happen in older (pre-Octane) versions of Ember if you have your component in all the right places, but your component doesn't have a dash in its name. As per the docs, components are required to have at least one dash in their names:
Components must have at least one dash in their name. So blog-post is an acceptable name, and so is audio-player-controls, but post is not. This prevents clashes with current or future HTML element names, aligns Ember components with the W3C Custom Elements spec, and ensures Ember detects the components automatically.
If you try to create a component without a dash in its name, Ember won't find it and will give you this error.
It appears this requirement has been lifted in more recent versions of Ember, where components start with a capital letter to distinguish them from native HTML elements.
From the documentation:
Helpers allow you to add additional functionality to your templates beyond what is included out-of-the-box in Ember. Helpers are most useful for transforming raw values from models and components into a format more appropriate for your users.
It looks like you are using a non-defined helper. So please look through (and maybe provide) some more of your log output. You are probably using an undefined helper in one (or multiple) of your .hbs-files.
component and file name must be the same. This solution worked for me.
I am quite sure the answer to my question is somewhere in some docs, I read many pages, on official and unofficial websites, many related questions on SO, but my google-fu seems not developed enough to help me find the answer, so here I am.
In my team we are using Ember-cli for some web application. We have the classic app/templates folder in which we put the .hbs of each "controller" we have. In those handlebars templates, we use components which are in app/templates/components.
We recently have reached a point where the app/templates/components is too big. I thought that it would be good idea to split them into sub-directories, e.g.
app/templates/product1 containing specific-to-product1 components + the base product1 handlebar (the one called in app/router.js, a "controler's hbs").
app/templates/product2 containing specific-to-product2 components + the base product2 handlebar (the one called in app/router.js, a "controler's hbs").
But when I do that, it doesn't work and displays a white page:
If I move the "controler's hbs" from app/templates to app/templates/product1, I have a whole white page with nothing loaded.
If I move a component from app/templates/components to app/templates/product1, the "controler's hbs" shows, but I have an empty block where my component is supposed to be.
I don't know if I have to configure ember for it to recursively search for handlebars in the app/templates folder, and/or if I have to change the router.js, and how to call my components so ember knows where they are.
Thanks in advance,
Benjamin
Override the templateName property.
App.YourStuffComponent = Ember.Component.extend({
templateName: 'components/intoDir/your-stuff'
});
Demo: http://emberjs.jsbin.com/jenafa/2/edit?html,js,output
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)
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).
I'm just getting started with Ember. I'm a little confused on some things, as the guides on the main site seem to indicate different ways of working.
In the main docs (http://emberjs.com/documentation/), it indicates that a controller should just extend an ordinary Ember object like this:
Ember.Object.extend();
Which works fine for me.
Then in the guide to using Routing (http://emberjs.com/guides/outlets/) it suggests that there is a Controller object type that you can extend:
Ember.Controller.extend();
This doesn't work for me, and if I simply try to console.log Ember.Controller, its undefined.
I'm using Ember version 0.9.8.1.
Should I worry about this, or should I just carry on with extending Objects as my controllers?
0.9.8.1 is aging, and unfortunately even the guides on the site are ahead of it -- use latest (at https://github.com/emberjs/ember.js/downloads) to keep up with the most current best practices.
Update: 1.0-pre is out (emberjs.com), so that is the best to use. The docs / guides have been brought up to date.
I think #pauldechov means the specific "latest" build which you can find here: https://github.com/emberjs/ember.js/downloads
But also keep in mind that the documentation and "latest" are not always in sync.