It's pretty complicated to set such kind of interactions when you have that templates. Your components are fully independent, but they should have a parent-child connection, since they are actually the parent and a child.
A more suitable approach for me is below.
app/index/template.hbs
{{#buttons-list buttons=property_with_a_correct_list_from_the_index_controller}}
app/components/button-list/template.hbs
{{#each button in buttons}}
{{#button-icon data=button}}
{{/each}}
app/components/button-icon/template.hbs
<div>{{data.title}}</div>
{{#button-tooltip data=data.tooltip}}
app/components/button-icon/component.js:
export default Ember.Component.extend({
tagName: 'button',
...
});
app/components/button-tooltip/template.hbs:
{{#if isPicture}}
<img src={{data.image}} />
{{else}}
{{data.text}}
{{/if}}
app/components/button-tooltip/component.js:
export default Ember.Component.extend({
tagName: 'div'
isPicture: function() {
this.get('data.type') == 'image'
}.property('data.type')
});
And the property_with_a_correct_list_from_the_index_controller
should look like this
[
{title: 'Cat', tooltip: {isPicture: true, image: 'cat.png'}},
{title: 'Dog', tooltip: {isPicture: true, image: 'dog.png'}},
{title: 'Rat', tooltip: {isPicture: false, text: 'Nobody wants to see a picture of a rat!'}}
]
Let's review it:
- I moved edged tags in the components to the controllers in a
tagName
property
- A content of a tooltip now directed by the tooltip itself, not by the parent icon component
- Now a tooltip and an icon have clear relationship, so the icon finally has any reasonable way to control it
For now let's determine your high-level requirement for the sample:
- User should see a tooltip when hovers an icon.
- User shouldn't see a tooltip when leaved an icon.
As you can see the icon component totally controls the tooltip visibility. In this case I'd consider an approach with conditional template. For example:
app/components/button-icon/component.js:
export default Ember.Component.extend({
tagName: 'button',
showTooltip: false,
didInsertElement: function() {
self = this // this will be redefined inside of hover function
// hover in
this.$().hover(function() {
self.set('showTooltip', true);
,
// hover out
function() {
self.set('showTooltip', false);
}
},
// more code here to handle other stuff
});
app/components/button-icon/template.hbs
<div>{{data.title}}</div>
{{#if showTooltip}}
{{#button-tooltip data=data.tooltip}}
{{/if}}
As you can see, your sample is rewritten in a more clear way, where you can see a approach to control tooltip visibility. I'd recommend to use such approach only in case when you need to control the tooltip visibility.
Back to
more code here to handle other stuff
For this I would recommend to not discard your approach with binding of a property. Just create a property with a required state in the button-icon
component and make a corresponding computed property in the button-tooltip
component, which will be listening for changes in the property.
Example:
app/components/button-icon/component.js:
export default Ember.Component.extend({
tagName: 'button',
tooltipProps: [],
didInsertElement: function() {
self = this // this will be redefined inside of hover function
// hover in
this.$().hover(function() {
self.get('tooltipProps').addObject('showIt');
, function() { // hover out
self.get('tooltipProps').removeObject('showIt');
});
this.$().on('click', function() {
self.get('tooltipProps').addObject('makeitRed');
});
},
// more code here to handle other stuff
});
app/components/button-icon/template.hbs
<div>{{data.title}}</div>
{{#button-tooltip data=data.tooltip props=tooltipProps}
app/components/button-tooltip/component.js:
export default Ember.Component.extend({
tagName: 'div'
isPicture: function() {
this.get('data.type') == 'image'
}.property('data.type'),
onPropsChange: function() {
if (this.get('props.makeItRed')) {
// make it actually red directly by the own component code
}
}.observe('props') // an observer because you need to do actions here, if you want to change the internal state use a computed property
});
P.S. But the first approach I like more %)