I have a component that represent a map and after an action in my controller I want to call a method on the component to center the map. The code looks like this
<
You can use on
to have your component listen for an event from the controller, then you can use trigger
in the controller to emit an event.
So in your component you might have something like this:
didInsertElement : function(){
this.get('controller').on('recenter', $.proxy(this.recenter, this));
},
recenter : function(){
this.get("mapView").centerMap()
}
And in your controller you could have :
actions : {
centerMap : function () {
this.trigger('recenter');
}
}
Bind a component property to the controller property in the template:
{{google-map componentProperty=controllerProperty}}
Then observe the component property in the component:
onChange: function () {
// Do your thing
}.observes('componentProperty')
Now every time controllerProperty
is changed in the controller, onChange
in the component will be called.
From this answer, second paragraph.
I think it's OK to have a reference in your controller to your component. It's true that your component encapsulates it's own behaviour, but public methods like reload
etc. are perfectly fine.
My solution for this is to pass the current controller
to the component and set a property on the controller within the component.
Example
template.hbs:
{{#component delegate=controller property="refComponent"}}
component.js:
init: function() {
this._super.apply(this, arguments);
if (this.get("delegate")) {
this.get('delegate').set(this.get("property") || "default", this);
}
}
Now in your controller you can simply get a reference to your component with this.get("refComponent")
.
Steffen
In Ember, views (Components are glorified views) know about their controller, but controllers do NOT know about views. This is by design (MVC) to keep things decoupled, and so you can have many views that are being "powered" by a single controller, and the controller is none the wiser. So when thinking about the relationship, changes can happen to a controller and a view will react to those changes. So, just to reiterate, you should never try to access a view/component from within a controller.
There are a few options I can think of when dealing with your example.
Make the button part of your component! Components are meant to handle user input, like button clicks, so you may want to consider making the button a part of the map component and handle clicks in the actions hash of your component. If this buttons is always going to accompany the map component, then I certainly recommend this approach.
You could have a boolean property on your controller like isCentered
, and when the button is clicked it's set to true. In your component you can bind to that controller's property, and react whenever that property changes. It's a two-way binding so you can also change your locally bound property to false if the user moves the map, for example.
Controller:
...
isCentered: false,
actions: {
centerMap: {
this.set('isCentered', true);
}
}
...
Component:
...
isCenteredBinding: 'controller.isCentered',
onIsCenteredChange: function () {
//do your thing
}.observes('isCentered'),
...
Jeremy Green's solution can work if you mix in the Ember.Evented mixin into the controller (which adds the pub/sub trigger
and on
methods)
Inside of your component call:
var parentController = this.get('targetObject');
See: http://emberjs.com/api/classes/Ember.Component.html#property_targetObject