Bubbling and waterfalling events

I am trying to bubble up an event to a parent and waterfalling it down to another child. All three are of different kinds.

Initially, I was trying to just bubble it to the parent and then obtaining the data there and setting the values from the parent. Ex:
this.$.scroller.$.childB.setSomething()
But, while I was able to call the components of 'this', I was unable to call the components of the scroller. Chrome told me that all the components of my components weren't defined. I am curious as to why this is the result, and if I did something wrong here.

So next, I tried waterfalling down the event that I bubbled up. The child will catch the event, but all the data is gone. Here is a bit of code:

// The originator
bubbleTap: function(inSender, inEvent){
	lastTapped = inSender.index;	// set the lastTapped var to the tapped object
	this.bubble('onNameplateTap');	// bubble the event up to CreateFeedback
},

// The parent
nameplateTap: function(inSender, inEvent){
	this.hidePeerScreen();
	this.showReviewScreen();
	this.waterfall('onPrepareReview');
},

// The child that needs the data
prepareReview: function(inSender, inEvent){
	this.log(inEvent);
	var nameplate= inEvent.originator.getTappedNameplate();
	this.$.card.$.nameplate.setNameString('asdf'); 
	return true;
}
I have tried this a ton of different ways, but none of them have been successful. I believe the current code creates a new (blank) event to send down instead of sending the initial event down with the correct info. I haven't been able to find any example of this, although the documentation suggests it is possible. It also discusses signals as an inferior alternative, which I tried, but the child did not pick up the signal.

Thanks.

Comments

  • edited June 2013
    You need to pass inEvent as the second argument to this.waterfall or this.bubble, otherwise it doesn't know what event object to send. You also can include a third argument, the value of the event's sender, but that will default to this.

    In your code, you'd write:
    // The originator
    bubbleTap: function(inSender, inEvent){
    	lastTapped = inSender.index;	// set the lastTapped var to the tapped object
    	this.bubble('onNameplateTap', inEvent);	// bubble the event up to CreateFeedback
    },
    
    // The parent
    nameplateTap: function(inSender, inEvent){
    	this.hidePeerScreen();
    	this.showReviewScreen();
    	this.waterfall('onPrepareReview', inEvent);
    },
    
    // The child that needs the data
    prepareReview: function(inSender, inEvent){
    	this.log(inEvent);
    	var nameplate= inEvent.originator.getTappedNameplate();
    	this.$.card.$.nameplate.setNameString('asdf'); 
    	return true;
    }
  • Thanks, that was a pretty simple fix.
    I do have another question though.

    Here, I execute
    this.$.card.$.nameplate.setNameString('asdf');

    and it fails because of the same reason my first method was failing. I know I can get around it be creating the kinds differently, but I would prefer to do it like this. Is there a reason why kind2 in
    this.$.kind1.$.kind2
    always fails for me? I always get 'cannot call method 'x' of of undefined' and that this code never grabs kind2.

    Thanks again.
  • edited June 2013
    It's generally very bad form to have multiple $ levels in a call. Each level should be isolated from each other so you have good encapsulation.

    Remember that the $ hash has all the controls you own. You own all the controls mentioned in your components section, even if they're not a the top level. Have you tried just this.$.kind2? I'd guess that in your intial code, the contents of the scroller aren't actually owned by the scroller, the scroller is just its container.
  • That worked. I guess I had the idea of ownership wrong, and I thought that the component a level up owned the component below. This way is much cleaner though. I remember I did fix this problem once, but it was the first day I was messing around with Enyo in JSFiddle. I tried access lower components the correct way later, but it didn't work once (I probably had another error somewhere), so I figured I needed multiple $s to go lower.

    Thanks for the help again.
  • One case where this doesn't work is if you use enyo.Repeater, as that ends up creating proxy objects in the tree for each of the repeated components sections... there, you need to ask the repeater for the row's item, then reference it's owner items. However, there's an event hack that lets those owned items still send events up to the owner of the repeater.
Sign In or Register to comment.