Override application controller values - ember.js

I have an application that on many pages has a map.
This map needs to be removed/hidden on some pages.
I have some properties defined at the application controller level:
app.ApplicationController = Ember.ObjectController.extend({
isAuthenticated: false,
showMap: true
});
and I have another controller set for a route, let's say :
app.RegisterController = Ember.ObjectController.extend({
showMap: false
});
In the ui the application controller properties are taken in consideration.
I would like to override the usage of the property from the application controller and take in consideration the value from the controller set for the current route.
Any solution ?

Ember provides a fairly comprehensive set of computed property helpers that can be used to combine properties. Combined with the controller needs system which allows access to other controllers, these can be used to create a computed property that takes into account a property from the applicationController and the local controller:
App.ApplicationController = Ember.Controller.extend({
showMap: true
});
App.ChildController = Ember.Controller.extend({
needs: ['application'],
showMap: false,
combinedShowMap: Ember.computed.and('controllers.application.showMap', 'showMap')
});
This example creates a computed property, combinedShowMap that is the boolean AND operation of the applicationController's showMap and the childController's showMap.
JSBin example

Related

Ember. Communication between components. Breadcrumbs

I've implemented a custom function in a component that takes the information from the URL and returns an array, with the right name and link in order to behave as a breadcrumb.
The problem is that the last step in the process, the app has to do a transitionTo a different route/model in a completely different URL.
How can I display the breadcrumb in the final template(in the different route)?
If you're using EmberSimpleAuth, just store it in the session:
App.BreadcrumbController = Ember.Controller.extend({
session: Ember.inject.service(),
//...
this.get('session').set('data.breadcrumbs', breadcrumbs)
});
App.anotherController = Ember.Controller.extend({
session: Ember.inject.service(),
breadcrumbs: Ember.computed.alias(this.get('session.data.breadcrumbs')),
});
If not, you can store the array of breadcrumbs in the application controller. You can then use it wherever you want.
App.BreadcrumbController = Ember.Controller.extend({
//inject application controller so you can set a property on it
application: Ember.inject.controller(),
//...
//then once you have the breadcrumbs, store them in the application controller
application.set('breadcrumbs', breadcrumbs)
});
App.anotherController = Ember.Controller.extend({
//inject application controller and get the breadcrumb property
application: Ember.inject.controller(),
breadcrumbs: Ember.computed.alias(application.get('breadcrumbs')),
});

Ember component cannot use access controller property via "needs"

I'm trying to change a controller's property from a component as follows(JSBIN example http://jsbin.com/gevuhu):
App.CategoryManagerController = Ember.Controller.extend({
selectedCategory: null,
});
App.BlogPostComponent = Ember.Component.extend({
needs: ['categoryManager'],
selectedCategory: Ember.computed.alias('controllers.categoryManager.selectedCategory'),
actions:{
selectedCategory: function (){
this.set('selectedCategory',1);
}
}
});
but getting the error Property set failed: object in path "controllers.categoryManager" could not be found or was destroyed.
Is it that we cannot use "needs" in components ?
Ember Components are completely isolated from surrounding context including controllers (see here). That's the bad news. The good news is that if you pass selectedCategory into the component, it will become 2-way bound, so any change to it in the component will be known by your controller.
So, your controller could be something like:
App.ApplicationController = Ember.ObjectController.extend({
needs: ['categoryManager'],
selectedCategory: Ember.computed.alias('controllers.categoryManager.selectedCategory'),
selectedCategoryChanged: function(){
alert("NEW CATEGORY: " + this.get('selectedCategory'));
}.observes('selectedCategory')
});
and then in your application template, you can say
{{ blog-post selectedCategory=selectedCategory }}
See a working example here
In later version like 2.2. We'll be writing this as:
App.ApplicationController = Ember.Controller.extend({
categoryManager: Ember.inject.controller("categoryManager")
});
and now, categoryManager will now have the controller named categoryManager.

Emberjs: cross-controller binding failing because 'content' doesn't exist yet

I'm trying to use the 'needs' feature to allow one controller to obtain a value from another. Here's a JSFiddle that shows a stripped-down version of my app before binding a value: http://jsfiddle.net/kevinwh/WRxnE/4/
App.ApplicationController = Ember.ObjectController.extend({
init: function() {
this._super();
},
dishClicked: function() {
console.log('clicked');
this.incrementProperty('clickCount');
}
});
App.DishController = Ember.ObjectController.extend({
needs: ['application'],
init: function() {
this._super();
},
//clickCountBinding: 'controllers.application.clickCount'
});
Basically, my ApplicationController has a clickCount property that is updated (by an action) whenever one of the Dish links is clicked. Clicking on a link also activates the DishRoute via linkTo.
Now I'd like the contained DishController to also have access to ApplicationController's clickCount. So I add the 'needs' property and a clickCountBinding property (which will have to be uncommented in the JSFiddle). Then, when I click on a link I get a complaint:
assertion failed: Cannot delegate set('clickCount', 0) to the 'content' property of object proxy : its 'content' is undefined.
Apparently the binding is being activated before the model content is set on the controller. Since the controller is being set up by the linkTo, my DishRoute.model() and DishRoute.setupController() methods are not invoked. Also, the DishController.init() method isn't even called before the binding error happens.
I considered the possibility that I should just stick a content member object into the class (commented out in the JSFiddle), but doing that gives a bizarre result: the click count is incremented separately for the different links. Interesting, but not what I'm after.
So - how do I share the clickCount value across these controllers? Is there some other way to set up the content in the DishController so that the binding will work?
You've just slightly misunderstood the error message.
The issue is that you've subclassed the ApplicationController from ObjectController even though it doesn't have an underlying content object to proxy to, you should just user Ember.Controller in this case.
That being said, if you have a counter you should probably default it to zero anyway.
App.ApplicationController = Ember.Controller.extend({
clickCount: 0,
dishClicked: function() {
console.log('clicked');
this.incrementProperty('clickCount');
}
});
App.DishController = Ember.ObjectController.extend({
needs: ['application'],
clickCountBinding: 'controllers.application.clickCount'
});

What is the new official way to get from a controller the value of an instance variable of an other one controller

What is the new way to get from a controller the value of an instance variable of an other controller.
For instance, I was using before I was using before
App.router.get("applicationController.isLoopingEnabled") to access the value and App.router.set("applicationController.isLoopingEnabled") to set the value of isLoopingEnabled variable from my PlaybarController instance.
I just want to know what is the best practice right now on Ember RC3. I'm experiencing a lot of problems to upgrade from the pre-version.
There isn't "one way" to access properties of different controllers anymore. It depends on where you want to access it from.
To access a controller from another controller:
Use the Controller's needs depedency
Example:
App.PostsController = Em.ArrayController.extend({
someValue: 1
});
App.CommentsController = Em.ArrayController.extend({
needs: ['posts'],
postsValuePlusOne: function() {
return this.get('controllers.posts.someValue') + 1;
}).property('controllers.posts.someValue')
});
To access a controller from a route:
App.PostsController = Em.ArrayController.extend({
someValue: 1
});
App.CommentsRoute = Em.Route.extend({
renderTemplate: function() {
var someValue = this.controllerFor('posts').get('someValue');
}
});
To access a controller from a view:
App.PostsController = Em.ArrayController.extend({
someValue: 1
});
App.PostsView = Em.View.extend({
someValueBinding: 'controller.someValue'
});
If you want to access a value of a controller other than the view's controller (for example CommentsController, use the controller's needs: controller.controllers.comments.someValue
Finally,
There is a global method to access any controller, but use this only for debugging and testing, never in production:
var postsController = App.__container__.lookup('controller:posts')

How can I bind a property in my controller to the application controller if ApplicationController is automatically initialized by Ember?

I have a property in my Ember controller which I wanted to bind to a property in application controller but since I have not created an instance of ApplicationController, thus I am not able to give the reference. Something like,
MyApp.ApplicationController = Em.Controller.extend({
userName: 'hohenhiem'
});
MyApp.SampleController = Em.Controller.extend({
nameBinding: 'application.userName'
});
i have a jsFiddle to show my problem here
You are looking for the needs property. In a controller you can specify dependencies and then use them as follows:
MyApp.SampleController = Em.Controller.extend({
needs: ['application'],
nameBinding: 'controllers.application.userName' });
http://jsfiddle.net/yCr4F/1/