The story with Index Controllers, Views, Templates? - ember.js

I've created the following route in Ember:
this.resource('password_reset', { path: '/password_reset' }, function() {
this.route("request");
this.route("claim");
});
The Ember debugger -- which I LOVE btw -- shows me this results in the following:
I have created two templates so far:
/templates/password_reset.hbs
/templates/password_reset/index.hbs
When I go to the URL http://my.server.com/#/password_reset I would expect that -- based on what the debugger's telling me -- that the 2nd template listed (aka, password_reset/index) above is used but in fact it uses the frist one. What doing? Anyone care to shed some light on this mystery?

Ok, I think it can be chalked up to a newbie question. The relationship between these two controllers/views/templates becomes far more clear when I put an {{outlet}} into the /password_reset template. Then I can see that the password_reset/index shows up as the outlet. The index, in effect, becomes the default outlet when a sub-route is not defined. Pretty basic but somehow I didn't get it until I bumped into a wall or two.

Related

Is there any way to render Handlebars templates on server via Backbone in front-end?

edited
This question is in addition to previous Handlebars with Backbone template not rendering problem in which browseser was not rendering forms at all now the problem was solved for the form but returns another error which is possibly also with the rendering.
I have an app with Backbone on front-end and Express in back-end with express-handlebars templates and I was trying to change from Underscore templating to Handlebars while still leaving backbone logic behind. So the way I did it - installing handlebars via Bower and then required it.
app.ContactView = Backbone.View.extend({
//....
template: Handlebars.compile( $('#tmpl-contact').html() ),
//....
});
instead of
app.ContactView = Backbone.View.extend({
//....
template: _.template( $('#tmpl-contact').html() ),
//....
});
But it returns errors and I don't really get what causes them.
When I try to load a page, for example:
http://192.168.33.10:3000/contact/
It doesn't shows any errors in the browser. But if I move to:
http://192.168.33.10:3000/about
which doesn't even have Backbone logic behind it returns an error:
You must pass a string or Handlebars AST to Handlebars.compile. You
passed undefined
Which means that template is compiled before the DOM loads on the page. But my Backbone script is loading after html script e. g. after the {{{body}}} element. Also if there is a problem with an order I should get this error on every, not only when moving to another.
So I think the cause is some kind of a conflict between front-end handlebars and express-handlebars on a server. How to solve this, preferably that templates to be rendered via expHbs instance?
If the only change that you made was:
template: Handlebars.compile( $('#tmpl-contact').html() ),
to:
template: _.template( $('#tmpl-contact').html() ),
it wouldn't cause the problems you're describing. As the error message told you "You passed undefined", and undefined wouldn't have worked with the Underscore code either.
It seems more likely that you changed something else, and that change caused the issue you described. However, without more code (ideally a JS Fiddle) it's hard to say what.
Problem solved by loading each Backbone part as a separate file for its route.

How to add templates to sub-directories in Ember?

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

How to render component/helper from another one?

I have render-component ( source ) which used to render components/helpers from controller fields. It worked fine for ember 1.9.1 but after updating up to ember 1.12.1 I found changes in API. After updating code I restore simple cases ( like render view by name from some property ). But largest part of functionality still broken.
I'm interesting about where can I read more about such things like
env ( which used inside components/helpers internal implementation )
morph ( I understand that it's a part of html-bars, but I'm interested in more documentation )
hooks ?
Can anyone share some experience at creating such helper ? Or way to find solution in such cases? ( I mean that this things not fully documented )
P.S. I know about component-helper from ember 1.11 -- but it doesn't allow render helpers ( with params) and using it I should define all properties in template. And when name of component/helper is dynamic -- I should pass different params / attributes.
Thx in advance
P.P.S
Some examples of functionality I want restore with my helper ( more examples and motivation you can find at helper page -- I just want note difference between my helper and build-in component-helper ):
{{#render-component componentName _param='btn-component' action="addSection"}}
{{render-component 'pluralize-component' ___params=hash}} // hash = { count:ungrouped.content.meta.total, single:"Object"}
{{#render-component 'componentName' _param=paramName someOption=someOptionValue}}
You've got quite a few questions here, but to answer the one in your title: Ember 1.11 introduced the component helper that allows you to dynamically render components.
componentName: 'someComponentName'
...
{{component componentName param=value someAction='someMapping'}}
This article contains most of the information one might use to implement what I think you're getting after (compared to the standard component helper).
One notable out-of-the-box solution they suggest is the use of the (almost deprecated) dynamic-component addon.
{{dynamic-component
type=theType
boundProperty=foo
staticProperty="bar"
onFoo="fooTriggered"
}}
Hopefully this (and other suggestions from the article) steer you towards your solution.
I was looking for an answer to this, ended up with a solution myself.
My scenario was that I wanted to pass in a component to another component and render it inside that component, which sounds like what this question was aiming for.
For those who don't clearly know how the {{component}} helper works:
Use it to render another component.
{{component "component-name" param1="value" param2="value"}}
This would work exactly the same way as:
{{component-name param1="value" param2="value"}}
For my scenario, I did this:
In the template invoking the first component:
{{my-comp-1 comp=(component "my-comp-2" param1="value" param2="value") other-param="value"}}
In my-comp-1's template, use the attribute used for the component:
{{component comp}}
That was all I needed to do.
This works perfectly as of Ember 2.7.0.

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).

Ember.Controller doesn't exist?

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.