Advanced Configuration
edit this pageIn addition to supplying static values for configurations options, some of the Ractive options can be specified using a function that will resolve when the ractive instance is instantiated, and re-evaluated upon ractive.reset().
An option function may be supplied to either Ractive.extend() or new Ractive().
Option functions receive the post-configured data
option as the first argument and this
in
the function refers to the ractive instance being instantiated.
Bear in mind that the ractive instance is in the process of being configured, so not all options
are necessarily configured yet, and functional methods like observe
or set
should not be called.
Template
The template can be specified using the return value of an option function:
new Ractive({
template: function ( data ) {
return data.foo ? '<p>hello world</p>' : '<div>yes, we have no foo</div>';
},
data: { foo: true }
});
The return value can be any of the valid template options: a preparsed template,
a string that will parsed as a template, or an string starting with #
that refers to an element id from which
the template should be retrieved.
In general, these should be sufficient for most use cases. However, if you need to dissect templates or extract
partials dynamically, the template option function also receives a second argument
with a helper parser object p
that offers the following methods:
p.fromId( id )
Retrieves the template from the DOM
<script>
tag specified byid
. Leading#
is optional. Make sure to settype='text/ractive'
on the<script>
tag or the browser will try and execute the contents as javascript and you'll get an exception.p.isParsed( template )
Test whether the supplied instance has already been parsed
p.parse( template [, parseOptions ] )
Parses the template via Ractive.parse(). If no
parseOptions
specified, defaults to those of the current instance. Full Ractive runtime must be loaded.
During a ractive.reset() operation, an option function for a template will be re-evaluated and if the return value changes the ractive instance will be re-rendered.
Used in a component, an option function can be used to dynamically control the template from the parent and self-update when the value changes:
<widget template='{{template}}'/>
var Widget = Ractive.extend({
template: function( data ) {
return data.template
},
init : function() {
this.observe( 'template', function( newTemplate, oldTemplate ) {
if( newTemplate === oldTemplate ) { return; }
this.reset( this.data )
}.bind(this), {init: false} )
}
});
Partials
The value for a named partial can also be specified using a function:
new Ractive({
template: '<div>{{>dynamicPartial}}</div>',
partials: {
dynamicPartial: function ( data ) {
return data.condition ? '<p>hello world</p>' : '<div>yes, we have no foo</div>';
}
}
});
Partial option functions also received the helper parser p
as the second argument. This is useful in
partials as you cannot return an element id from a partial function and must use p.fromId
to return
the template content of an element.
Partial functions also cannot directly return the string token of a registered partial. Instead, return the value from the ractive instance:
partials: {
dynamicPartial: function ( data ) {
// assuming data.partial is the string token of a registered partial:
return this.partials[data.partial];
}
}
Components
A component value can be specified using an option function. The return value can either be a component or (unlike partials) the string token of a registered component:
Ractive.components.view1 = Ractive.extend({...});
Ractive.components.view2 = Ractive.extend({...});
new Ractive({
template: '<div><dynamicComponent/></div>',
components: {
dynamicComponent: function ( data ) {
return data.foo ? 'view1' : 'view2';
}
}
});
Data
The data option function can either return a value or use the prototype inheritance chain to construct the
data object. Use this._super
to call the parent data option. Ractive will handle integrating
static data options and data option functions. If a return value is specified, further parent data options
will not be considered.
var Component1 = Ractive.extend({
data: {
formatTitle: function (title) {
return '"' + title.toUpperCase() + '"';
}
}
});
var Component2 = Component1.extend({
data: function( data ) {
this._super( data );
data.scale = 5;
}
});
var ractive = new Component2({
data: { foo: 'bar' }
})
// r.data: { foo: "bar", formatTitle: function, scale: 5 }
The data object instance passed to the instantiated ractive instance will always be retained as
the ractive.data
instance, unless a return value is specified from an option function in which
case that return value instance will be used as ractive.data
Copying Parent Data
Because parent data is common to all instances, you can use an option function to return a unique copy of the data.
var Shared = Ractive.extend({
data: {
foo: { bar: 42 }
}
});
var shared1 = new Shared();
var shared2 = new Shared();
shared1.set( 'foo.bar', 12 );
shared2.get( 'foo.bar' ); // returns 12
var NotShared = Ractive.extend({
data: function () {
return {
foo: { bar: 42 }
};
}
});
var notShared1 = new NotShared();
var notShared2 = new NotShared();
notShared1.set( 'foo.bar', 12 );
notShared2.get( 'foo.bar' ); // returns 42
Asynchronous Data
A data option function can be a handy way to fetch asynchronous data and supply initial synchronous values:
data: function () {
$.get( 'somedata.url', function( data ) {
this.set( '', data );
}.bind(this) );
return {
foo: 'default'
};
}
Specifying a Model
Another use of the data option function is to provide a model:
data: function ( data ) {
return new Model( data );
}
If you use a constructor guard clause (currently popular for new
-less use of javascript constructors),
you can directly supply the model:
function Model ( data ) {
if ( !( this instanceof Model) ) { return new Model( data ); }
// model setup
}
var MyComponent = Ractive.extend({
data: Model
});
var r = new MyComponent({
data: { foo: 'bar' }
})