I can instantiate (sub)components manually using tags, but I don't know how to do it dynamically, or, how to insert and remove different components in the same area using tags.
Today I instantiate each (sub)component this way:
Ractive.load( '/templates/global/example.html' ).then( function ( Example )
{
ractive.components.example = new Example( { el : 'aside' } );
});
But the new (sub)component can't see the data of it's parent instance in mustache, only his own data.
Inside the DynamicComponent we created a SelectUser variable and returned it, so that if we pass usera as a prop UserA component is rendered or if we pass userb as a prop UserB component is rendered on the screen. Let’s use our dynamic component now by importing it.
Our application will be made of 2 React.js components: Application component is a contrainer component - it encapsulates our entire React.js application. Image component on the hand - renders a single image. Let's create the Image component first: Code snippet 1.
In the practical world, you may add all other features to it just like any other component in react. Though this tutorial is using plain ReactJS, you can use the same component structure for react-native apps as well. The card component we will be creating will look something like this -
This will have Header, Body and Footer as its submodules. For the tutorial purpose, I am keeping this card component very simple and not adding any complex functionality to it. In the practical world, you may add all other features to it just like any other component in react.
Here's a dynamic component:
Ractive.components.dynamic = Ractive.extend({
template: '<component/>',
components: {
component: function() {
return this.get('name');
}
},
oninit: function(){
this.observe('name', function(){
this.reset();
}, { init: false});
}
});
Just pass in the name of the component it should implement:
<dynamic name='{{name}}'/>
See it in action below
Ractive.components.a = Ractive.extend({ template: 'I am A {{foo}}' });
Ractive.components.b = Ractive.extend({ template: 'I am B {{foo}}' });
Ractive.components.c = Ractive.extend({ template: 'I am C {{foo}}' });
Ractive.components.dynamic = Ractive.extend({
template: '<component/>',
components: {
component: function() {
return this.get('name');
}
},
oninit: function(){
this.observe('name', function(){
this.reset();
}, { init: false});
}
});
var r = new Ractive({
el: document.body,
template: '#template',
data: {
foo: 'foo',
list: ['a', 'b', 'c'],
name: 'a'
}
});
<script src="http://cdn.ractivejs.org/latest/ractive.js"></script>
<script id='template' type='text/ractive'>
{{#each list}}
<input type='radio' name='{{name}}' value='{{.}}'>{{.}}
{{/each}}
<br>
<dynamic name='{{name}}'/>
</script>
Would like to upvote @martypdx's answer more than once. Inspired by his answer, I came up with something I'd like to share. It adds the following things:
Create multiple instances of a type of Component (Ractive.extend)
Component instances are alive and can receive messages from external listeners even if they have been unrendered.
Here is my fiddle: https://jsfiddle.net/vikikamath/z5otgzpL/9/
// Inspired by http://stackoverflow.com/a/31080919/405117
var mapper = {
'A': function(instanceId){
var handleAData;
return Ractive.extend({
template: 'I am A this is my data: <ul>{{#datas}}<li>{{.}}</li>{{/datas}}</ul>',
data: {
datas:[]
},
onrender: function() {
handleAData = function(txt){
this.push('datas', txt);
}.bind(this);
r.on(instanceId, handleAData);
},
onunrender: function() {
r.off(instanceId, handleAData);
}
});
}
,'B': function(instanceId){
var handleBData;
return Ractive.extend({
template: 'I am B this is my data: <ul>{{#datas}}<li>{{.}}</li>{{/datas}}</ul>',
data: {
datas:[]
},
onrender: function() {
handleBData = function(txt){
this.push('datas', txt);
}.bind(this);
r.on(instanceId, handleBData);
},
onunrender: function() {
r.off(instanceId, handleBData);
}
});
}
,'C': function(instanceId){
var handleCData;
return Ractive.extend({
template: 'I am C this is my data: <ul>{{#datas}}<li>{{.}}</li>{{/datas}}</ul>',
data: {
datas:[]
},
onrender: function() {
handleCData = function(txt){
this.push('datas', txt);
}.bind(this);
r.on(instanceId, handleCData);
},
onunrender: function() {
r.off(instanceId, handleCData);
}
});
}
,'D': function(instanceId){
var handleDData;
return Ractive.extend({
template: 'I am D this is my data: <ul>{{#datas}}<li>{{.}}</li>{{/datas}}</ul>',
data: {
datas:[]
},
onrender: function() {
handleDData = function(txt){
this.push('datas', txt);
}.bind(this);
r.on(instanceId, handleDData);
},
onunrender: function() {
r.off(instanceId, handleDData);
}
});
}
}
/* arbitrarily select a component */
function pickRandomComponent() {
return String.fromCharCode(Math.floor(Math.random() * Object.keys(mapper).length) + 65);
}
var DynamicComponent = Ractive.extend({
template: '<component/>',
components: {
component: function() {
return this.get('name');
}
},
oninit: function(){
this.observe('name', function(){
this.reset();
}, { init: false});
}
});
var r = new Ractive({
el: 'main',
template: '#template',
components: {
dummy: Ractive.extend({ template: 'Welcome message' }),
dynamic: DynamicComponent
},
data: {
foo: 'foo',
list: ['dummy'],
name: 'dummy',
textdata: ''
},
oninit: function() {
this.on("sendDataToCurrentComponent", function() {
r.fire(this.get('name'), this.get('textdata'))
}.bind(this));
this.on('addComponent', function(){
var rndComponent = pickRandomComponent();
var now = Date.now();
var componentInstanceName = rndComponent + '-' + now
this.components[componentInstanceName] = mapper[rndComponent](componentInstanceName)
this.push('list', componentInstanceName);
}.bind(this));
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/ractive/0.7.3/ractive.min.js"></script>
<script id='template' type='text/ractive'>
<button on-click="addComponent">Add</button>
<div>
<input type="text" value="{{textdata}}" placeholder="Send Text to current component" width="900" on-blur="sendDataToCurrentComponent"/>
</div>
{{#each list}}
<input type='radio' name='{{name}}' value='{{.}}'>{{.}}
{{/each}}
<br>
<dynamic name='{{name}}'/>
</script>
<main></main>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With