Darshan
Darshan

Reputation: 1011

Can an Ember component observe a controller property?

I have a controller and a component. when the component is rendered, it is passed on in this manner:

{{modal-filter feature=feature parentController=this.controller}}

where feature is a param passed in via controller to handlebars, and parentController is the controller.

Now, in the controller itself, there is an property (an array). let's call that array requiredValues.

Now within a controller/component itself, we can easily set:

valueObserver : function(){
     ...
}.observes('requiredValues')

However, I need to observe this controller property from a the modal-filter component. So in the modal-filter component, what would I put as the observer function:

valueObserver : function(){
     ...
}.observes(???)

Upvotes: 11

Views: 10439

Answers (2)

Kingpin2k
Kingpin2k

Reputation: 47367

What you shouldn't do, but I'll tell you how for completeness

If you're passing the controller in, you can just watch an item on the parentController property, though I wouldn't recommend this at all.

valueObserver : function(){
     ...
}.observes('parentController.requiredValues')

This would assume the entire array is being replaced, not just an item added, or changed.

Item Added or Removed

valueObserver : function(){
     ...
}.observes('parentController.requiredValues.[]')

Item Property foo changed on one of the requiredValues items

valueObserver : function(){
     ...
}.observes('[email protected]')

What you should do

Instead of passing in the controller, just pass in the property, and observe the property.

{{modal-filter feature=feature property=someProperty}}


propertyObserver : Ember.observer('property', function(){
     ...
})

Upvotes: 16

user663031
user663031

Reputation:

Passing an entire controller to a component is a massive code smell. It violates the basic principle of component encapsulation. If the "component" is so tightly coupled to the controller, then it's a view, from where you can access the controller by simply saying this.controller. Input to components should be strictly through parameters passed in when they are invoked. Output from components is through send, which the controller can map to some behavior of its choosing in its view's template by saying {{my-component action='eraseHardDisk'}}.

You don't need to directly observe anything on the controller from within the component. If you call the component with {{my-component param=someProperty}}, then any change to the controller's someProperty will automatically be propagated to the param of the component. The component can then define some computed property on param, or observe it, or use it in its own template where it will be automatically kept up-to-date.

Upvotes: 22

Related Questions