How to add templates to sub-directories in Ember? - ember.js

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

Related

How to inject components in whole application in ember.js

I'm on developing a ember-cli project where I have created many reusable components. I want these components in every template(hbs) file. I can do {{component1}} {{component2}} {{component3}} in each template but this looks redundant to me since I've to write all these lines in every template. All I want to know is if I can inject components in all the templates like way services are injected into routes, components etc where ever I need.
Example of how I inject services is below
/intializers/session-object.js
export function intialize (application){
application.inject('route','session','service:session');
application.inject('controller','session','service:session');
application.inject('component','session','service:session');
application.inject('adapter','session','service:session');
});
I tried injecting the components into templates as similar as above.
/intializers/session-object.js
export function intialize (application){
application.inject('template','my-component','component:my-component');
});
As expected, the above code fails. No where in the ember guides is mentioned that I can inject components in templates. But, wanted to know if anybody did this before.
I believe there could be a strong reason why ember is not allowing us to inject components into templates.
Any help in explaining the reason why this cannot be implemented in ember.js is great or providing a solution if it can be implemented is awesome. Thanks in advance guys.
Injecting to template is not meaningful.
You can create a partial template and put that common components there then use that partial.
-common.hbs
{{nav-bar}}
{{error-messages}}
another.hbs
{{partial 'path-to-common-template'}}

Using non-trivial REST API and Ember

We're new to Ember, and our intended (ember-cli) app first works by opening a project (which we can think of a JSON object), and then acting on various sections of that project with various functions. We have this "pick your project first" approach neatly encapsulated in a Django REST api structure, e.g.
/projects/ lists all projects
/projects/1/ gives information about project 1
/projects/1/sectionA/ list all elements in sectionA of project 1
/projects/1/sectionA/2/ gives information about element 2 of sectionA in project 1
/projects/1/sectionA/2/sectionB/... and so on.
We made relatively good progress with the first two points in Ember using ember-data and this.store('project').find(...) etc. However, we've come unstuck trying to add further to our url (e.g. points 3., 4., and 5.). I believe our issues come from routing and handling multiple models (e.g. project and sectionA).
The question: what is the best way to structure the routes in Ember.js to match a non-trivial REST API, and use ember-data similarly?
Comments:
the "Ember way", and stuff working out of the box is preferred. Custom adapters and .getJSON might work, but we're not sure if we'll then lose out on what Ember offers.
we want the choice of project to affect the main app template. E.g. if a project does not have "sectionA", then a link to "sectionA" is not displayed in the main app. And, if the project does have "sectionA", we need the link to be to e.g. "/project/1/sectionA", i.e. dependant on the project open.
This seems similar to handling users (i.e. first I must "pick a user" and then continue), where the problem is solved outside of the URL (and is similar to using sessions as we have done in the past). However, we specifically want the project ID to be inside the URL, to remain stateless.
Bonus questions (if relevant):
how would we structure the models? Do we need to use hasMany/belongsTo and, if so, is this equivalent to just loading the whole project JSON in the first place?
can ember-data handle such complex requests? I.e. "give me item 2 from sectionA of project 1"? Can it do this "in one go", or do there have to be nested queries (i.e. "first give me project 1" and then from this "give me sectionA" and then from this "give me item 1")?
Finally, apologies if this is documented well somewhere. We've spent nearly a week trying to figure this out and have tried our best to find resources -- it's possible we just don't know what we're looking for.
I think this one will be a good thing to read: discuss.emberjs.com/t/… - you've got Tom Dale and Stefan Penner involved in the thread
My suggestion would be to change it to query params:
/projects?id=1&selectionA=a&selectionB=b
then, you won't have such problems. And yes, you can still use all the hasMany and belongsTo fields.
If there's anything unclear, I'll provide you with a longer answer (if I'm able to).
Check out ember-api-actions and ember-data-actions also ember-data-url-templates
Here's a few more resources from a blog I found. ember-data-working-with-custom-api-endpoints and ember-data-working-with-nested-api-resources

Where do we store css styles in and Ember CLI Pods app?

I am reading http://www.ember-cli.com/#stylesheets which says:
Ember CLI supports plain CSS out of the box. You can add your css
styles to app/styles/app.css and it will be served at
assets/application-name.css.
Is there a folder structure convention I should follow? Something like:
app/styles/application.css
app/styles/users/index.css
app/styles/users/new.css
etc
Or is the convention to store all custom css in app.css?
Is there special consideration I should take into account when applying this to a Pods app?
You are not alone in the struggles of dealing with the dreaded global CSS problems that make growing an app unwieldy.
Luckily for you a solution is just around the corner in Ember 2.0 which will be dropping this summer. You can take advantage of this feature now however if you are feeling up to it or simply want to see what I'm talking about in regard to Ember Component CSS by a core member of Ember.js.
https://www.npmjs.com/package/ember-component-css
This isn't a full solution to your problem of course because its simply for components, but since components are an essential part of the Ember workflow now I think you'll find that stashing the CSS/SASS with them will be handy in a pods folder structure.
Most people seem to be breaking css files down into folders named after their routes for organizational purposes.
Update: Pods will be deprecated in a future version of Ember in favor of the Ember core team's new adaptation of a module unification system for managing project resources. You can read more here: https://github.com/emberjs/rfcs/blob/master/text/0143-module-unification.md
We develop add-on that lets you put your sass files in your pods directory!
Give it a try:
https://github.com/DudaDev/ember-cli-sass-pods
Say you got contacts route and contact-box component.
Generate regular route and component:
ember g route contacts -p
ember g component contact-box -p
Then, use ember-cli-sass-pods power and generate style:
ember g style contacts -p
ember g style components/contact-box -p
Your awesome file structure would be:
app/
app/contacts
app/contacts/route.js
app/contacts/template.hbs
app/contacts/style.scss
app/components/
app/components/contact-box
app/components/contact-box/component.js
app/components/contact-box/template.hbs
app/components/contact-box/style.scss
I'm no Ember Guru, however I wanted to chime in with some helpful conventions and tools the Ember community is adopting regarding stylesheets as we embrace a component based future.
Note requires: ember-cli and scss.
Via this post: An Agile Design Manifesto.
You don't necessary need to insert all your stylesheets into a pod structure, to get the benefits, as long as you...
"Organize SCSS by Route & Component"
For components, the article suggests you want to keep your selections global:
> stylesheets/components/_flash_messages.scss
/*
Base Styling for the Flash Messages component - how it will appear globally.
*/
.flash-messages {
background-color: $default-flash-color;
}
For resources you can leverage ID selectors and Ember's conventions to ensure that a template with a given ID only appears once and your SCSS code might look like:
> stylesheets/routes/_posts.scss
/*
Global Styling for the "Posts" resource.
It's an ID because it's guaranteed to only ever appear on the page once.
Thanks Ember!
*/
#posts {
#import "show";
#import "new";
#import "edit";
}
You can use this to override global styling and create a faux CSS scope.
The imported show route styles could then be:
> stylesheets/routes/posts/_show.scss
/*
Styling here is specifically for this on the "Show" route of the "Posts" resource.
Most likely, it's empty, but it's a good place to override the global appearance of components, and ensure those changes are contained to this route only.
*/
#posts-show {
.flash-messages {
background-color: $posts-show-flash-color;
}
}
Given these recommendations you could use a module like: ember-cli-sass-pods to allow you to generate stylesheets in your routes or component pods. You would then need to add the #import declarations to the generated files in your app.scss file.

Lazy Loaded Ember Application

I am typically searching for answers here but I finlly gotten to the point where I can't find a good answer.
I am looking to build an ember app which only initially loads in the things that it needs just to start and open the main route. All other controllers, views, templates, etc. Would be loaded lazily when a specific route gets triggered.
I have found a good example of how to accomplIsh this here:
http://madhatted.com/2013/6/29/lazy-loading-with-ember
My main question is to determine what build tools out there support this theory of lazy loading application code? So far, I've seen that Brunch, Yeoman, and Ember App Kit seemed to minify and concatenate all the scripts and templates. I am very happy with minification but need those files separate. I have thought about just putting this code into the app/assets location so that it gets copied over without concat but it does not get minified.
Does anyone have a solution? Thanks!
You can do this with brunch by adding the following to your brunch config
files: {
javascripts: {
joinTo: {
'javascripts/app.js': /^app(\/|\\)(?!admin)/, // concat everything in app, except /app/admin
'javascripts/vendor.js': /^vendor/,
'javascripts/admin.js': /^app(\/|\\)admin/ // concat only /app/admin
}
}
}
Grunt (used in yeoman and ember app kit) is ridiculously flexible, so I'm sure you can set up the same thing there by diving into Gruntfile.js
The question was: "I am looking to build an ember app which only initially loads in the things that it needs just to start and open the main route. All other controllers, views, templates, etc. Would be loaded lazily when a specific route gets triggered.".
Ember expects to have anything it needs right there when the page gets loaded. I wouldn't be wrong, but lazy loading of routes doesn't seem to be a feature of Ember. Ember CLI is the same. It uses bundling and minification to reduce the overload. But everything should be there to make it work.
Instead, people like me would like to load things only when they are required.
When you try to implement lazy loading in Ember, everything should be represented by a module (file.js): a route, a module; a controller, a module; and so on.
You should follow a schema (like POD), to which apply a mechanism to find things where they are supposed to be.
Every module should know its dependencies. But some of them are very frequent (route, controller, template).
You should use a module loader for the browser. It can be requirejs or whatever you like. But ES6 is at the door. Let's think about that.
Many people use beforeModel hook to achieve a result. I did it, and it works, if you don't use link-to component. Otherwise everything crashes. Why? Because of href computed property. When a link-to has been inserted, an href is calculated for it. Because of that, Ember looks for the route where the link points to. If the route doesn't exist, one is created from route:basic.
A solution could be the preloading of all the routes represented by all link-tos inserted in the page. Too much expensive!
An integration to this answer can be found at Lazy loading route definitions in Ember.js
For an initial solution to lazy loading of routes organized in POD, have a look at https://github.com/ricottatosta/ember-wiz. It is an ES6 based approach, which relay on SystemJS as module loader.

The story with Index Controllers, Views, Templates?

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.