Access to controller's param in Ember view - ember.js

Let's say I have IndexController and it has a param called isEditing.
I also have index template which {{render list}} template.
I have a problem in using isEditing property in list.
You can find an example here http://emberjs.jsbin.com/kabumuca/1/edit
Did I miss something here?

Ahoy!
So, here is the working jsbin: http://emberjs.jsbin.com/kabumuca/9/edit.
Essentially, the reason why it wasn't working was because of a misinterpretation of the view helpers. When you're using the {{render}} helper, it ties your controller to the view you are rendering. As you weren't specifying a literal view (just the template and model), it was creating virtual view and controller for you.
See here: The Render Helper - Ember.js

This might help
App.ListController = Ember.Controller.extend({
isEditing: Ember.computed.alias('parentController.isEditing')
});

Related

Ember 1.0.0 - can no longer access controller from view?

I'm using a render helper inside a template, which renders a searchbox with a typeahead.
Essentially (code removed for brevity):
script(type='text/x-handlebars', data-template-name='index')
{{render search}}
script(type='text/x-handlebars', data-template-name='search')
{{view App.TaggableInput valueBinding="searchText"}}
Which gives me a SearchController separated from the IndexController.
Inside App.TaggableInput I'm grabbing searchController to do some checking on the keyUp event:
App.TaggableInput = Ember.TextField.extend({
keyUp: function(e){
var controller = this.get('controller');
// Do stuff with the controller
}
});
On Ember RC7, I can access the controller inside theview as you'd expect with this.get('controller').get('searchText').
However in Ember 1.0.0 this.get('controller') returns the view, and whatever I do I can't get searchController.
I can't find any related info on the ember website regarding what's changed or what I'm supposed to do... for now I'm sticking with RC7.
Any ideas? I've spent hours on it this morning and can't figure it out. Thanks.
UPDATE: Fixed!
I swapped out this.get('controller') for this.get('targetObject') and it works as before. Had a peruse through a recent commit in ember source to find it...
Thanks for your suggestions guys!
I guess that in your code
App.TaggableInput = Ember.TextField.extend({
keyUp: function(e){
var controller = this.get('controller');
// Do stuff with the controller
}
});
this line
var controller = this.get('controller');
gets the controller associated to your (subview)
Try to use this line instead to access the route's controller:
var controller = this.get('parentView.controller');
Currently, the {{render}} helper takes 2 arguments, the first is the context, the second is the model.
I recommend using this method and following the naming convention for the model's controller rather than setting the controller explicitly.
You can find the docs here:
http://emberjs.com/guides/templates/rendering-with-helpers/#toc_the-code-render-code-helper
Accessing controllers from views was also being tracked in this discussion:
https://github.com/emberjs/ember.js/issues/1712#issuecomment-31183940
I think Ember has not changed its behaviour. I created a JSBin, where i managed to get the controller successfully.
What i did was creating a simple View and show it via {{render}} helper:
View:
App.FooView = Ember.TextField.extend({
didInsertElement : function(){
console.log(this.get("controller.constructor"));
console.log(this.get("context.constructor"));
}
});
Template:
{{render foo}}
And the first log statement showed an associated controller. Can you see any conceptual difference between my code and yours?

Error while using currentView feature of Ember.ContainerView in an each helper

I would like to be able to swap views in a each helper using Ember.ContainerView.
{{#each itemController="person"}}
<li>{{view Ember.ContainerView currentViewBinding="cv"}}</li>
{{/each}}
It yields the following error:
Something you did caused a view to re-render after it rendered but before it was inserted into the DOM
It does work when I strip off the each helper.
I know there is other ways to do that but it seems to me that it's a good use case for a ContainerView.
Here is the jsFiddle : http://jsfiddle.net/fblanvil/Mr3D7/2/
Something you did caused a view to re-render after it rendered but before it was inserted into the DOM
I found the problem, have a look at your modified and working jsfiddle.
Basically what you where doing wrong and thus the error was that you where calling create which should be rather extend.
See here for the changed part:
...
cv: Ember.View.extend({
templateName: 'name'
})
...
Hope it helps.

How do I bind a controller to the view when the controller is create by Ember.js

this question is slightly related to How to display the “content” of an ObjectController?
However, in the provided solution and all other examples I can find the controllers are always created explicitly. The nice thing about Ember.js is that the Route takes care of mostly everything. So I don't want to create the controller but want to bind it to a view:
{{view App.myview controllerBinding="App.applicationController"}}
You can see the complete example in this fiddle. The example is not that great because Ember usually sets the controller of a child view to its parent view.
In the end I need to know, how I can access a controller which is created by Ember from a view.
Thanks for any help!
Update:
I provided the wrong fiddle or it did not save my changes. Here is the link to the right version: http://jsfiddle.net/ncaZz/1/
What should I provide in line 9 in the templates?
From the view you can access the controller with
this.controller
If you need other controllers than your view controller you can use the needs in the viewcontroller:
App.DatasetEditController = Ember.ObjectController.extend({
needs: ['mappingIndex']
});
and then use:
this.controller.mappingIndex
You don't really need to bind to it. You can access the controller from the view by calling it like this.
this.get('controller');
Updated Answer:
You really should not have your click event inside your view. Your actions should either be in your controller or your router.
Your template should become
<span style="background-color: green" {{action doStuff}}>
Click
</span>
and you should have a controller that should have this
App.MyController = Em.Controller.extend({
needs: ['application'],
doStuff: function(){
this.get('controllers.application').foo();
}
});
Also, the MyView and MyController should be capitalized, because when extending these items from ember that are not instances, and the capitalization is required. The view should only really have stuff in the didInsertElement that handles special things like any kind of jquery animations or initializing a date picker. But, the "ember way" is to have action in the router or controller.

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

How can I bind the element ID for an Ember View?

My model "content.id" contains a string, e,g "123":
{{view Em.TextArea idBinding="content.id"}}
Instead of just setting the id of this view to "123", I'd like it to be "message-123", basically customizing the string being used. Sadly, Ember does not allow bindings to be functions, which would solve my problem (I could define such a function on the controller).
What's the best way to achieve this?
You could define a computed property in the controller (or elsewhere):
The controller
MyApp.ApplicationController = Ember.Controller.extend({
content: "a-content",
editedContent: function() {
return "message-" + this.get('content');
}.property('content')
});
The view
MyApp.FooView = Ember.View.extend({
    tagName: 'p'
});
The template (where content is a String, here)
{{#view MyApp.FooView elementIdBinding="editedContent"}}
{{content}}
{{/view}}
And the JSFiddle is here.
EDIT
How can the view see the property editedContent since it belongs on the ApplicationController controller?
The router, after started, automatically render the ApplicationView, or its template when there is no ApplicationView defined. If you want more detail, I suggest you to read the Ember guide: Understanding the Ember.js Router: A Primer.
And {{editedContent}} directly get the controller editedContent property, because the default view context is its controller, as you can read in Ember Blog - 1.0 Prerelease:
The {{#view}} helper no longer changes the context, instead maintaining the parent context by default. Alternatively, we will use the controller property if provided. You may also choose to directly override the context property. The order is as follows:
Specified controller
Supplied context (usually by Handlebars)
parentView's context (for a child of a ContainerView)