What is it?
Ractive.js is a template-driven UI library, but unlike other tools that generate inert HTML, it transforms your templates into blueprints for apps that are interactive by default.
Ractive-Require is an extension to Ractive.js that provides the support to require features on demand. A feature is composed by a HTML template file, and its JavaScript and CSS assets. They are not loaded on the page as long as the user does't need to use it.
The final goal is to create large webapps that loads and uses features only when necessary.
The project

The project is maintened by an enthusiast community. They work together on enhancing the engine by making new features, fixes and more on GitHub.
Examples
The basics
Here is a page
$('#basics-help').click(function() {
var opened = $('#basics-help').data('opened') || false;
opened = !opened;
$('#basics-help')
.data('opened', opened)
.html(opened ? 'Close the help' : 'Open the help');
if (opened) {
// This loads all the rv-require elements
// It loads the element assets and HTML
// then it calls the controller of each element
BasicsPage.require();
}
else {
// We assume "BasicsPage" is a Ractive element
// When this element calls the .require() method
// it takes its children in the childrenRequire property
BasicsPage.childrenRequire[0].teardown();
}
});
HELP
Help content
(function() {
'use strict';
// When the .require() is fired and after the load of the
// rv-require assets, the "help" controller is fire
window.Ractive.controller('help', function(component, data, el, config, done) {
// "component" is a magic function that create the Ractive element
// It uses the HTML template loaded and the target rv-require element
// to create the view.
var Help = component({
data: data
});
done();
});
})();
.help {
position: absolute;
top: 4.2rem;
right: 0;
bottom: 0;
width: 50%;
border-left: 1px solid #ececec;
padding: 1rem;
background: white;
}
Partials
Here is a page
$('#partials-help').click(function() {
var opened = $('#partials-help').data('opened') || false;
opened = !opened;
$('#partials-help')
.data('opened', opened)
.html(opened ? 'Close the help' : 'Open the help');
if (opened) {
PartialsPage.require();
}
else {
PartialsPage.childrenRequire[0].teardown();
}
});
<div class="help">
<!-- Include your Ractive partials in your view -->
<!-- They will be replaced by the content inside rv-partial tags -->
<h4>HELP {{> title}}</h4>
<p>
Help content:<br />
{{> content}}
</p>
</div>
(function() {
'use strict';
window.Ractive.controller('help', function(component, data, el, config, done) {
var Help = component({
data: data
});
done();
});
})();
.help {
position: absolute;
top: 4.2rem;
right: 0;
bottom: 0;
width: 50%;
border-left: 1px solid #ececec;
padding: 1rem;
background: white;
}
Databinding
{{title}}
$('#databinding-edit').click(function() {
var opened = $('#databinding-edit').data('opened') || false;
opened = !opened;
$('#databinding-edit')
.data('opened', opened)
.html(opened ? 'Edit the title' : 'Close the edition');
if (opened) {
DatabindingPage.require();
}
else {
DatabindingPage.childrenRequire[0].teardown();
}
});
Edit the title
(and drink a {{drink}})
(function() {
'use strict';
window.Ractive.controller('edition', function(component, data, el, config, done) {
var Edition = component({
data: data
});
done();
});
})();
.edition {
position: absolute;
top: 4.2rem;
right: 0;
bottom: 0;
width: 50%;
border-left: 1px solid #ececec;
padding: 1rem;
background: white;
}
.edition .info {
margin-top: -1.4rem;
font-size: 1.4rem;
}
On demand
Here is a page
$('#on-demand-require').click(function() {
OnDemandPage.require();
});
$('#on-demand-chat').click(function() {
OnDemandPage.require('chat');
});
$('#on-demand-profile').click(function() {
OnDemandPage.require('profile');
});
$('#on-demand-reset').click(function() {
for (var i = OnDemandPage.childrenRequire.length - 1; i >= 0; i--) {
OnDemandPage.childrenRequire[i].teardown();
}
});
{{title}}
...
Here is the chat
Cascading elements
Here is a page
$('#cascading-elements-help').click(function() {
var opened = $('#cascading-elements-help').data('opened') || false;
opened = !opened;
$('#cascading-elements-help')
.data('opened', opened)
.html(opened ? 'Close the help' : 'Open the help');
if (opened) {
// Require only the help-full feature
CascadingElementsPage.require('help-full');
}
else {
CascadingElementsPage.childrenRequire[0].teardown();
}
});
HELP
(function() {
'use strict';
window.Ractive.controller('help-full', function(component, data, el, config, done) {
var HelpFull = component({
data: data
});
// Immediatly after its creation,
// the feature require its sub-features
// and fire done() after
HelpFull.require().then(function() {
done();
});
});
})();
<div class="article">
<h4>{{title}}</h4>
...
{{> content}}
</div>
;
Installation
Use the CDN version:
<script src="https://cdnjs.cloudflare.com/ajax/libs/ractive-require/0.6.5/ractive-require.min.js"></script>
Or copy the dist folder into your project and include ractive-require.js
or ractive-require.min.js
(production) file in your HTML page after Ractive.
Use it
Require a feature
A feature is a package of an HTML template and its assets. Use the HTML tag <rv-require>
to put your feature unloaded in your page. This tag requires a name and a src attribute. The name is not unique, it's used to avoid loading several times the same assets files in the browser. The src is used to locate the feature "package".
The missing file extension is assumed because we want to load the entire feature package.
At this point, nothing happens, the feature is only loaded on demand.
To load and create your feature view, you have to use the Ractive container view by calling the .require()
of its parent.
// Start by creating the parent view from the <body> element
var ractive = new Ractive({
el: 'body',
template: document.body.innerHTML
});
// Call the require() method to fire the rv-require injection
ractive.require().then(function() {
console.log('done');
});
.require()
is a promise thats provide a .then()
method to callback after the end of the process.
The cycle of a require
When you fire .require()
on a ractive
element, all of its <rv-require>
children are required in the view (except those with a ondemand
attribute).
First, Ractive-Require adds the following to the <head>
element:
components/button.css
components/button.js
Then it registers the components/button.html
template in its memory (by xhr). The feature is loaded.
In the <rv-require>
src attribute the extension is not set because Ractive-Require will load 3 different types of files
The HTML template will still be a Mustache template with data-binding, but for now, it's just a string.
Control a feature
When a <rv-require>
is loaded, all of its registered Ractive.controller
are fired. You can wrap it for your feature to get the feature definition and other things:
// Declare a controller for the rv-require named "button"
Ractive.controller('button', function(component, data, el, config, done) {
// "component" is a pre-configured view function.
// It already contains template, partials and the targeted DOM element.
var ractive = component();
// You can get the pre-configured details with the "config" object.
// When your controller logic is complete, call done().
done();
});
Now your feature is totally applied in the DOM and you can control it!
Cache
Each feature template is cached by its name. If you declare:
The second button does not reload the JavasScript and CSS files in the head and it re-uses the template content previously loaded.
HTML only
To avoid loading the CSS or JavaScript files, you can add no-script="true"
and/or no-css="true"
:
On demand
With Ractive.require()
all of the <rv-require>
are fired except those with a ondemand
attribute.
To have the ability to require only some of features, you can use the ondemand
attribute:
Ractive.require()
has no effect on the button. To fire it, you have to specify Ractive.require('button1')
.
With the same ondemand attribute value, you can make groups of features loaded together.
Double databinding
You can pass two types of arguments in a <rv-require>
:
- Direct value with the
data-*
parameter. - Double databinding value between the parent and the child with the
data-bind-*
parameter.
The *
is the property name fetched in data.
Ractive.controller('button', function(component, data, el, config, done) {
console.log(data.id);
// With the first button, data.id gets the 5 direct value.
// With the second, data.id gets the value of the parent view "ractive.data.model.id"
// If the parent value "model.id" changes, the value is directly changed in the child too.
// If the child value "model.id" changes, the value is directly changed in the parent too.
// If you pass an object, it will not be cloned but directly sent.
var ractive = component({
data: data
});
});
It's also possible to bind in one way only:
- Use
data-bindparent-*
to bind the values from the parent to the child. - Use
data-bindchild-*
to bind the values from the child to the parent.
Events
A component can listen its parent events and its parent can do the same with its children:
- Use
data-on-*
to bind the child event to a parent event (named*
). - Use
data-listen-*
to bind the parent event to the child event (named*
). - Optionnaly you can bind many events this these syntaxes:
data-on-*-*-*-...
anddata-listen-*-*-*-...
Ractive.controller('button', function(component, data, el, config, done) {
// The "button" component can fire the "click" event when the user clicks on it.
// So when the user click on the first button, the "buttonClick" event is fired too.
// Then it fires the "parentEvent" that fire the "parentclick" of the second button.
var ractive = component({
data: data
});
ractive.on('buttonClick', function() {
ractive.fire('parentEvent');
});
});
Partials
It's possible to define partials for a <rv-require>
that are used only on it.
A partial is a <rv-partial>
element defined inside the <rv-require>
.
It can takes a src
attribute or directly a HTML code. It must have a target
attribute with the name of the partial Mustache tag.
If no partial is defined in the <rv-require>
, it takes the parent partial inclusion.
Inside the feature template, use the standard {{> partial}}
partial include:
<!-- index.html -->
<rv-require name="button" src="components/button">
<!-- A partial from a HTML page -->
<rv-partial target="content" src="components/content.html"></rv-partial>
<!-- Or a direct HTML content -->
<rv-partial target="footer">
<div>The footer</div>
</rv-partial>
</rv-require>
<!-- components/content.html -->
<div class="content">
{{> content}}
{{> footer}}
</div>
Tips: To use Mustache inside a partial section, you can escape the Mustache code: \{{my-variable}}
.
Cascading requires
Inside a feature or partial template, it's possible to call other features. It works exactly the same as requiring a feature
in the page, you have to call ractive.require()
for the parent feature.
The sub-feature already contain its parents partials.
Scopes
Each <rv-require>
has its own scope. When you call ractive.require()
it doesn't look at the DOM parent or the children of the <rv-require>
on it.
When you create your feature with ractive = component()
, ractive contains two new properties:
- ractive.parentRequire: It's the instance of the parent feature.
- ractive.childrenRequire: It's an array filled by all of the children features.
Paths
In a feature or partial template, all of the next src
attributes of the <rv-require>
and <rv-partial>
elements are relative of the actual file:
Icon
Teardown
When you fire a ractive.teardown()
of a feature, it fires all of its children teardown after it cleans the DOM.
Your <rv-require>
is reseted but still in the DOM. So you can re-use .require()
on its parent to re-fire its controller.
Require a file directly
In your JavaScript, you can require another JavaScript and CSS files. Use Ractive.require(file)
.
The goal is to use the same cache as for <rv-require>
elements.
// Inject the js files sequentially
// The return is a Promise
Ractive.require('/public/jquery.js')
.then(function() {
return Ractive.require('/public/jquery-ui.js');
})
.then(function() {
return Ractive.require('/public/styles.css');
})
.then(function() {
console.log('Assets loaded');
});
// You can add a name to avoid many injections of the same file.
// Otherwise, it's the filename wich is used as name.
Ractive.require('jquery', '/public/jquery.js');
Static methods
.controller()
Ractive.controller( name, controllerFunc )
Register a controller for a specific feature. When the feature will be required, the controller will be fire.
name string
The name of the feature.
controllerFunc( component, data, el, config, done ) function
The controller function. It is fired each time the specific feature is required.
component( config )function
Create and return a Ractive view (new Ractive()) plugged on the actual feature DOM. It provide automatically the native el
, template
and partials
configurations. It also create the parents/children links and add Ractive-Require instance attributes and methods.
data object
Data configuration getted from the data-*
and data-bind-*
attributes.
el DOM element
rv-require DOM element.
config object
It contains the HTML (string) template and the partials.
done( ) function
The callback function to finish the initialization of the controller. The .then()
of the parent's .require()
will be fired.
.require()
Ractive.require( file )
Inject a .js
or .css
file in the head
tag. It returns a promise that it is fired when the file is completely loaded. If the file is already loaded, the promise is directly fired.
file string
The file to inject in the head. The total path will be used to knows if the file is already loaded.
Ractive.require( name, file )
Inject a .js
or .css
file in the head
tag. It returns a promise that it is fired when the file is completely loaded. If the file is already loaded, the promise is directly fired.
name string
The name of the file. Instead of the file path, this name will be used to knows if the file is already loaded.
file string
The file to inject in the head.
Instance attributes
.parentRequire
ractive.parentsRequire ractive object
Each ractive
instance required by its parent owns its reference by using ractive.parentsRequire
.
.childrenRequire
ractive.parentsRequire array
When a ractive
instance require its children, it became owner of this property with all of its children required in it.
Instance methods
.require()
ractive.require( )
Require all of its sub rv-require
DOM elements except those with a ondemand
attribute.
This method returns a promise that it is fired when the elements are totally loaded.
The ractive.require()
process steps:
-
Inject the CSS file of the feature in the
head
(Unless theno-css="true"
attribute is given in therv-require
child element). Wait the end of the file load to go to the next step. -
Inject the JavaScript file of the feature in the
head
(Unless theno-script="true"
attribute is given in therv-require
child element). Wait the end of the file load and execution to go to the next step. - Get the HTML template from the URL (xhr) and keep it in cache.
-
Call all the registered controllers from the
rv-require
name. - Fire the promise returned.
ractive.require( name )
Instead of the method without a name, this one require all of its sub rv-require
DOM elements with the ondemand
attribute filled by the name
.
name string
The name of the ondemand
children.
.findParents()
ractive.findParents( attribute, value )
Return an array
filled by all of the ractive
parents searched through the cascading ancestors matching the filter.
attribute string
The attribute name to filter the parents.
value string
The attribute value to filter the parents.
.findParent()
ractive.findParent( attribute, value )
Return the ractive
parent searched through the cascading ancestors matching the filter.
attribute string
The attribute name to filter the parents.
value string
The attribute value to filter the parents.
.findChildren()
ractive.findChildren( attribute, value )
Return an array
filled by all of the ractive
children searched through the cascading children matching the filter.
attribute string
The attribute name to filter the children.
value string
The attribute value to filter the children.
.findChild()
ractive.findChild( attribute, value )
Return the ractive
child searched through the cascading children matching the filter.
attribute string
The attribute name to filter the children.
value string
The attribute value to filter the children.