I'm trying to separate data per partials so that the data doesn't mix/overwrite globally.
The problem is that the main template does not re-render when partial's data changes.
The best I've accomplished so far is to get the partial to re-render in the main container, but not within the main template itself.
Am I missing something?
Here's the code (also on JS Bin):
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
<script src="https://code.jquery.com/jquery-2.1.4.js"></script>
<script src="http://cdn.ractivejs.org/latest/ractive.js"></script>
</head>
<body>
<div id="main"></div>
</body>
</html>
JS:
var partial = new Ractive({
template: '{{name.first}} {{name.last}}',
oninit: function () {
this.observe( function ( newValue, oldValue, keyPath ) {
console.info( 'newValue = %o, oldValue = %o, keyPath = %s', newValue, oldValue, keyPath );
});
},
data: {
name: {
first: 'John',
last : 'Doe'
}
}
}),
main = new Ractive({
el: '#main',
// template: 'Hello {{name}}!',
template: 'Hello {{>partial}}!',
partials: {
partial: function ( p ) {
// 1) Not working...
// return '{{name.first}} {{name.last}}';
// 2) ...also not working...
// return partial.template;
// 3) ...still not working...
// return ( p.isParsed( partial.template ) ) ? partial.template : p.parse( partial.template );
// 4) Kind of working... (static - does not re-render)
// return partial.toHTML();
// 5) Kind of working... (returning Promise!)
return partial.render( this.el );
}
},
data: {
name: 'John Doe'
}
});
// partial.set( 'name.first', 'Jane' );
You have two ways to do this. First, you can still use partials, but you force the context of the partial. Note, however, that the data will still reside in the same instance. In the following example, the partial picks up "John Doe" as data. But in the second partial usage, we force the jane
object to it, making it use first
and last
from jane
.
var main = new Ractive({
el: '#main',
template: 'Hello {{>personPartial john}} and {{>personPartial jane}}!',
partials: {
personPartial: '{{first}} {{last}}'
},
data: {
first: 'John',
last : 'Doe',
jane: {
first: 'Jane',
last : 'Dee'
}
}
});
main.set( 'jane.name.first', 'Jen' );
If you really total separation of the data, consider using components instead. In this case John
and Jane
are their own components. Note however, that if a component is missing data (like say John
didn't have first
), it will look into the parent (main
) for that data. If it happens to be there, it will use that (in this case foo
). You can use isolated:true
to prevent this behavior, like in Jane
. You can also explicitly pass data from the parent to the child by way of attributes.
var John = Ractive.extend({
template: 'Hello {{first}} {{last}}!',
data: {
last: 'Doe'
}
});
var Jane = Ractive.extend({
isolated: true,
template: 'Hello {{first}} {{last}}!',
data: {
first: 'Jane',
}
});
var Jay = Ractive.extend({
isolated: true,
template: 'Hello {{first}} {{last}}!'
});
var main = new Ractive({
el: '#main',
template: 'Hello {{>person}}! <john /> <jane /> <jay first="{{first}}" last="{{last}}" />',
partials: {
person: '{{first}} {{last}}'
},
components: {
john: John,
jane: Jane,
jay: Jay
},
data: {
first: 'foo',
last: 'bar'
}
});