There's a couple of possible solutions. I'm not sure what would qualify as idiomatic - generally, Ractive's philosophy is 'if it works, it's the right solution!' - I'm the author, but I'll leave it to the community to decide over time what is idiomatic.
1. Passing in functions at initialisation
If you were using d3 to create a scatterplot, typically you would do something like this:
d3.select( 'circle' ).data( points )
.enter().append( 'circle' )
.attr( 'cx', function ( d ) { return d.x; })
.attr( 'cy', function ( d ) { return d.y; })
.attr( 'r', 5 );
In other words, for each datum item in the array, we've supplied a function that extracts the value we need to plot its x and y position.
The Ractive equivalent would be to specify a function when initialising the component:
<!-- the template -->
<svg>
<path d='{{ points_to_path(points) }}'/>
</svg>
// let's create a chart component that assumes we get an array
// of points with an `x` and a `y` property
var Chart = Ractive.extend({
template: chart,
data: {
points_to_path: function(points) {
// is there a 'normalise' function? If so, normalise
// the data we've been given
if ( var normalise = this.get( 'normalise' ) ) {
points = points.map( normalise );
}
// turn a normalised `{x: x, y: y}` point into 'x,y'
var pointToString = function ( point ) {
return point.x + ',' + point.y;
};
// create the SVG path
return 'M' + points.map( pointToString ).join( ' ' );
}
}
});
// now, we need to create a function that tells the Chart
// component how to deal with the data we're about to give it
var chart = new Chart({
data: {
points: [[1, 2], [3, 4], [5, 6]],
normalise: function ( point ) {
return { x: point[0], y: point[1] };
}
}
});
So if you had an array of points with date
and value
properties, you'd just pass a normalise
function (or normalize
if you prefer American spelling...) that returned {x: point.date, y: point.value}
or whatever.
(Of course, you could overwrite the whole points_to_path
function instead if that was easier.)
2. Using partials
An alternative would be to use different partials in different situations:
<!-- widget template -->
<h2>This is a widget</h2>
<div class='contains-dynamic-contents'>
{{>inner}}
</div>
var widget = new Widget({
el: 'widgetContainer',
partials: {
inner: '<p>This paragraph will appear inside the div</p>'
}
});
This gives you a lot of freedom, but the line chart example is probably more cumbersome to adapt.
Inline components
The first method would also work with inline components - this example assumes you're using the development (0.3.8-pre) version, which will be released soon:
Ractive.components.linechart = Chart;
<div class='application'>
<h1>This is a chart</h1>
<linechart points='{{someData}}' normalise='{{someNormaliseFunction}}'/>
</div>
(Protip: you could specify a default normalise
function with Chart.data.normalise = someFunction
.)
The second method is a little trickier - you would have to dynamically switch out the partial on initialisation:
Chart = Ractive.extend({
beforeInit: function () {
this.partials.inner = ( someCondition ? thisPartial : thatPartial );
},
// ...
});
Sorry for the epic length of this response, hope the answer you wanted was in here somewhere!