I’m trying to make a small component – a dropdown menu with content provided by the calling template, but that has some common functionality (hence putting it in a component).
For example, I have a page template HBS:
{{#mydropdown-menu}}
// custom content for menu
{{/mydropdown-menu}}
What I want to be able to do is send an action from something inside the {{yield}} block back into the component, so it can handle it. For example, the page template might be something like this:
{{#mydropdown-menu}}
// custom content for menu
// button to close dropdown
{{/mydropdown-menu}}
Where pressing the button would call the ‘closeDropdown’ action inside the component. However, once I’m in the block in the main page template, I have no idea how to refer back to the component controller or actions. How can I do this, or is this what I even want to do?
Disclaimer: I’m still new to Ember, so it’s likely that I’m doing this the wrong way. If someone can let me know either a) how to do what I’m trying to, or b) why I shouldn’t be doing it that way, it would be appreciated!
The easier way to handle this is to bind a variable (or attribute) to the component and then inside have a computed property that observes what that bound variable is doing.
So for example imagine you have a parameter defined outside your component
dropdownClosed: true
then a component like this
{{my-component menu dropdownClosed=dropdownClosed}}
Then inside the component you can have something like this
handleDropdownChange: Ember.computed('dropdownClosed', function() {
var dropdownClosed = this.get('dropdownClosed');
if (dropdownClosed) {
// do something when true, like call another function or set something else
// you could even call your closeDropdown drop function
} else {
// do something when false, perhaps do nothing or perhaps close the menu and clean up state
}
}),
Aah, OK, I think I understand – so instead of trying to send something INTO the component from the calling block, I set up the component to watch a variable outside (in the page controller, say), and take action based on that.
Thanks for those pointers. I’ll play with that tomorrow, hopefully, and let you know how I go!
Yeah, there is a general principle encouraged by Ember (and React) called “data down, actions up”. Meaning that you should one way bind data variables to flow data down into your component hierarchy and use actions to send events back up the chain to a more centralized location for managing state such as routes, services, and controllers.
If you get stuck try posting a JSBin that demonstrates the problem. Sometimes easier to work through a focused code demo.
Well, I guess it depends? If you have, say, 8 different components, and you want to “send something into that component”, binding the component property to some external property might become quite unwieldy.
Of course, in the context of the original question, that’s probably the best solution.
But another approach that I have used is having my component send some action with itself as the first parameter, e.g.