How to get the component contents within Javascript when the sub-components are dynamically created?
Opened this issue · 2 comments
Description:
I've my reasons to re-invent the radio buttons with <button>
elements (like displaying "loading" icon and confirming database writes before displaying a "selected" tick). This is the stripped down version of my radio-buttons
component (playground):
Ractive.components['radio-buttons'] = Ractive.extend({
template: `{{>content}}`,
oninit: function(){
setSelection = (selection) => {
// do something else, like setting button colors
this.fire('select', selection)
}
this.on({
'*.init': (ctx, instance) => {
instance.on('click', (ctx2) => {
setSelection(instance.partials.content[0])
})
}
})
}
})
Ractive.components['radio-button'] = Ractive.extend({
template: `<button on-click="click">{{yield}}</button>`
})
new Ractive({
target: 'body',
template: `
<radio-buttons on-select="radioSelected">
<radio-button>hello</radio-button>
<radio-button>there</radio-button>
</radio-buttons>
`,
on: {
radioSelected: function(ctx, selection){
alert("selection is: " + selection)
}
}
})
However, when I try to create the radio-button
s with an {{#each}}
loop, buttons' on-click
handler doesn't work as intended: playground:
<radio-buttons on-select="radioSelected">
{{#each myArray}}
<radio-button>{{.}}</radio-button>
{{/each}}
</radio-buttons>
Expected output when we click on [a]
button: selection is: a
Observed output is: selection is: undefined
How can I make it work when I create the sub-components dynamically? What becomes different when we encapsulate the sub-components into the {{#each}}
loop?
Versions affected:
1.4
Platforms affected:
Browser
Note that if we don't use instance.partials.content[0]
and use instance.get('text')
, it works as expected (playground):
<radio-buttons on-select="radioSelected">
{{#each myArray}}
<radio-button text="{{.}}">{{.}}</radio-button>
{{/each}}
</radio-buttons>
So the problem is that we can't get the "content" of a component when it's created by a loop.
Since content
is a partial, it can be any template. In the case of loop, the content is an interpolator that references .
. As template content, there isn't really a value associated with it until it's rendered, so there are two things you could do:
- which you've already done in your second comment, is add some sort of value to the radio-button and pull that it from the event. This would also open things up to be more than just text.
- pull in the innerText from the element firing the event and use that as the value. This is only a solution if you only want your radios to show their exact value.
I suppose you could also combine those in something like this.