Reputation: 325
In Ractive.js how do you append properties to each object in an array passed into a component without making them available to the parent Ractive object?
A component might want to add extra properties to help it manage it's own internal state. Here is an example component behaving as a tab-control.
Component JS
var tabComponent = Ractive.extend({
isolated: true,
template: '#tabTemplate',
data: function(){
return {
items: [] // contains objects in this format { text: "title", detail: "detail" }
};
},
onrender: function() {
// add the extra property the component needs to be able to work
for(var i = 0; i < this.get('items').length; i++){
this.set('items[' + i + '].selected', false);
}
this.on('toggle', function(event){
var keypath = event.keypath + '.selected';
this.set(keypath, !this.get(keypath));
});
}
});
Component Template
<ul>
{{#items}}
<li>
<header class="tabHeader" on-click="toggle">{{text}} - Click to toggle!</header>
<div class={{selected ? '' : 'hidden'}}>{{detail}}</div>
</li>
{{/items}}
</ul>
A parent Ractive object could then use the component like this in its template.
<tab-control items="{{myItems}}"></tab-control>
The parent Ractive object can now see this extra property added purely for the components internal workings. This would be annoying if the parent Ractive object wants to serialise the data for an ajax call as it now has to know about a property from within a component. Is there anyway to prevent these component specific data properties becoming available outside of itself?
I've added an example here. When you print the model to the console window you can see the 'selected' property on every item within the array.
Upvotes: 1
Views: 755
Reputation: 3712
For these simpler use cases, you can just use another array to track selected state:
<ul>
{{#items:i}}
<li>
<header class="tabHeader" on-click="toggle('selected.' + i)">{{text}} - Click to toggle!</header>
<div class={{selected[i] ? '' : 'hidden'}}>{{detail}}</div>
</li>
{{/items}}
</ul>
Just make sure to add the data to your component:
var tabComponent = Ractive.extend({
isolated: true,
template: '#tabTemplate',
data: function(){
return {
items: [],
selected: []
};
}
});
see example
Otherwise, you can use a component for each item and then you get a relative data container for the item:
{{#items}}
<li>
<tab item='{{this}}'/>
</li>
{{/items}}
Which gives you more control and ability to do things like computed properties:
var tabComponent = Ractive.extend({
template: '#tab',
isolated: true,
data: {
selected: false
},
computed: {
upperDetail: '${item.detail}.toUpperCase()'
}
});
see http://jsfiddle.net/th2fywny/6/.
Upvotes: 4