4

I have a component which has, inside it, a list of child components (being drawn with a yield inside the parent component):

parent-component
  for item in items
    child-component item=item childProperty=parentProperty

Inside child-component, I have an observer on "childProperty", which correctly fires any time parentProperty changes. The problem is that I'd like to trigger that observer in a time when the property hasn't actually changed.

to do this, in my parent-component, I have:

this.notifyPropertyChange('parentProperty')

For some reason, this isn't making it to the child component. Here's a JS bin showing:

http://emberjs.jsbin.com/caxedatogazo/1/edit

While I'm happy to talk through my use-case more, I'm more interested in whether the JS bin should work, and if not, why..

Thanks so much for any help!

gcoladarci
  • 889
  • 9
  • 13

2 Answers2

8

When you call notifyPropertyChange on the controller, only observers registered within the controller are notified of the property change.

In your case, the observer is within the component controller and not the parent controller from where the notifyPropertyChange is called.

There is a hacky way to ensure that the component controller is notified of the property change. This can be done by adding the following method to the Component.

didInsertElement: function() {
  var controller = this.get('targetObject'); 
  controller.addObserver('foo', this, this.onDataChange);
},

What we are doing is, getting the parent controller, registering an observer for foo with the parent controller.

Here is the emberjs fiddle for the same: http://emberjs.jsbin.com/rajojufibesa/1/edit

Hope this helps!

ViRa
  • 714
  • 5
  • 7
  • Thanks, ViRa, this was very helpful. I feel weird accepting the answer since it's more of a work around, but I did vote this up! – gcoladarci Aug 27 '14 at 22:31
1

I expanded on ViRa's answer. This code below will allow your components to be passed data with different property keys on the controller. For instance, if the controller has a property data or wants to use the model from the router, the property key does not matter. The component does not need to have a fixed property key that is always used on the controller, such as "foo", instead it will dynamically find it.

didInsertElement: function() {
    var controller = this.get('targetObject');
    // Find the key on the controller for the data passed to this component
    // See http://stackoverflow.com/a/9907509/2578205
    var propertyKey;
    var data = this.get('data');
    for ( var prop in controller ) {
        if ( controller.hasOwnProperty( prop ) ) {
             if ( controller[ prop ] === data ) {
               propertyKey = prop;
               break;
             }
        }
    }
    if (Ember.isEmpty(propertyKey)) {
      console.log('Could not find propertyKey', data);
    } else {
      console.log('Found key!', propertyKey, data);
      controller.addObserver(propertyKey, this, this.onDataChange);
    }
  }

Update: Here is a JSBin: http://emberjs.jsbin.com/nafapo/edit?console,output

Glavin001
  • 1,276
  • 2
  • 17
  • 32