How to get current Ember app route from template - ember.js

I'm trying to set element class attributes based on current route. This is inside a navigation handlebars partial included in the Application handlebars template.
In my ApplicationController I can do something like:
isUsers: ( ->
#get('currentPath') == 'users.index'
).property('currentPath')
In the navigation template I want to do something like:
<a {{bind-attr class="isUsers:active:inactive"}} href="users"></a>
This doesn't work - inactive class is always set, even when in correct app path.
Any suggestions?

If you are defining the isUsers property in the ApplicationController, then are you sure you are using it in the application.handlebars or whatever template used by the ApplicationController? If you are using in a template which has a different Controller, make sure you use the following in your controller.
App.MyController = App.Controller.extend
needs: ['application']
In the template,
controllers.application.isUsers

Related

In Ember can the render helper get its model from the route instead of from its parameter?

On a template you can use the {{render 'route' model}} helper to embed a template and controller into another template, but this will set the model passed as an argument as the model. Is there a way to embed a route into a template but have the model come from the ebeded route's model hook? The reason why I can't use the parameter method is that the route's model is an RSVP hash and it depends on a dynamic segment.
If you need a template backed by the route, you shouldn't try to embed it somehow, just define new nested route in your router, create a tempalte and put {{outlet}} instead of {{render}}. It will do absolutely the same - resolve the route, fetch the model, setup controller and render given template.
If you still need to embed async data via {{render}} helper in some reason, you can use conditionals:
{{#if model.length}}
{{render 'template' model}}
{{/if}}

Access parent context from ember component block

I'm trying to work out how blocks work with ember components. With the following I'd expect project.name to be rendered for each loop.
// components/block-test.js
export default Ember.Component.extend({});
// index.hbs
{{#each project in projects}}
{{#block-test}}
{{project.name}}
{{/block-test}}
{{/each}}
But when I use this pattern project.name is not rendered. Is this the expected behaviour and if so how could I change it to get the above code to work?
component's are intentionally isolated, pass in anything you want to use (you don't need yield if you are passing it in)
{{#block-test project=project}}
--{{project.name}}--
{{/block-test}}
No Component template
--apple--
--dog--
--piano--
With yield
Component template
--{{yield}}--
Using Component
{{#block-test}}
{{project.name}}
{{/block-test}}
--apple--
--dog--
--piano--

Ember: Idiom for ArrayController to loop through same-named ObjectController

I have the following pattern recurring throughout my app, and I was wondering if there is a way to clean this up:
Array Controller:
App.ThingsController = Ember.ArrayController.extend()
Template for Array Controller (using Emblem)
each thing in controller
= render 'thing' thing
Object Controller:
App.ThingController = Ember.ObjectController.extend()
I don't like having that intermediary template that has only those two lines.
I looked into itemController as a potential solution but that doesn't seem to do what I want.
Instead of rendering inside your each loop you could just include the code, and then use itemController. This would consolidate your templates into one, but still allow you to use the ObjectController.
{{each thing in controller itemController="thing"}}
{{thing.name}}.id = {{thing.id}}
{{/each}}

{{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/

Uviews are not getting connected to controller

Ember has a Application which has ApplicationView, ApplicationController and 'application' named template and 'main' named outlet and all these connect automatically.
eg.
App.ApplicationView = Ember.View.extend();
and
App.ApplicationController = Ember.Controller.extend();
so whenever my application template renders its default controller is an automatic instance of
App.ApplicationController
whose properties i can access in the template. But why does it not works with other views and controllers, i.e. if I have
App.SongView = Em.View.extend()
and
App.SongController = Em.Controller.extend()
these two do not connect. I can use any property of
App.SongController
in my song template.
I can use like :
{{view App.SongView}}
and in the template:
<script type='text/x-handlebars' data-template-name='song'>
{{name}}
</script>
and if i have a name property in App.SongController then it wont get picked up because its not connected to the View.
although i can do it like this
{{view App.SongView controllerBinding='App.songController'}}
but this requires the instance of App.songController in my js file and also using this approach we are hard-coding the controller to the template.
What is the best way for this?
Update
I am also attaching a js fiddle for my problem here:
http://jsfiddle.net/anshulguleria/K6KPJ/
If you want to render a template and its associated controller and view, you can use the {{render}} template. It works similarly to this.render in the router.
{{render "song" song}}
This example will render the song template with an instance of App.SongController and App.SongView. It will set the song controller's model to the value of song in the current context.
Here is a working JSBin that illustrates how this works.