Search code examples
componentsractivejs

How to create Ractive's subcomponents dynamically and change them programmatically


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.


Solution

  • 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>