Object Instantiation in AFrameJS - Now Simplified

Note: This article has been updated because of an even more simplified method of object creation as shown in Object Instantiation in AFrameJS – Now Simplified Even More.

As of today, AFrameJS's AFrame.AObject compatible object instantiation is significantly improved. The old syntax for AFrame.construct was very readable but extremely verbose, resulting in code that sometimes had nearly as many lines to do instantiation as the base classes themselves. Bad jiji.

Because I like writing as little code as possible and still have maintainable code, I redid AFrame.construct, deprecating its use, replaced by AFrame.create, which too has been deprecated. All "Classes" that are created using AFrame.Class or AFrame.extend, and which have an init function, will have a "create" method attached as a static class function. Create can be called to create an instance of the class, create takes one parameter - the instantiation options.

In this post, I am going to give examples on how to use AFrame.create in its various incarnations. Then, I am going to show the updated "Add Friends" demo from the post "AFrameJS Tutorial – A Response to 'Backbone.js Tutorial – by noob for noobs'".

First a Little Background

Create is only added to classes that have the init function, in AFrame based applications, this normally means AFrame.AObject based classes. In AFrameJS, most classes do very little in their class constructors, instead deferring object initialization until the init function. This is so that Plugins can be bound to an object before the plugged object is initialized. This gives some advantages such as allowing plugins to add decorators to the plugged object, as well as the plugin being notified as soon as the plugged object is fully initialized.

To allow for the binding of objects and plugins, the normal sequence of object creation is:

  1. Instantiate the plugged object
  2. Instantiate, initialize, and bind plugins to plugged object
  3. Initialize the plugged object, passing to the init function any configuration

This is such a common paradigm in AFrameJS that the class' create performs all of this when given a configuration object.

Examples

AFrame.AObject Instantiation, no configuration

// Instantiate an AFrame.AObject, give it no configuration
// The only parameter is a constructor
var obj = AFrame.AObject.create();

AFrame.AObject Instantiation, with configuration

// Instantiate an AFrame.AObject, give it a configuration object giving a 
// cid for the object. The first parameter is the constructor, the second
// parameter is configuration
var obj = AFrame.AObject.create( {
   cid: 'SampleAObject'
} );

AFrame.AObject Instantiation, with a Plugin that has no configuration

// Instantiate an AFrame.AObject, give it a configuration object that 
// contains an array of Plugins. The only Plugin as an AFrame.Plugin, 
// with no configuration.
var obj = AFrame.AObject.create( {
   plugins: [ AFrame.Plugin ]
} );

AFrame.AObject Instantiation, with a Plugin that has configuration

This is the most complex case of instantiation, all others are variations of the examples already presented.
So that we can define which plugin to add as well as the configuration for that plugin, we use a 2d array.

// Instantiate an AFrame.AObject, give it a configuration object that
// contains an array of Plugins. The only Plugin as an AFrame.Plugin, 
// with no configuration.
var obj = AFrame.AObject.create( {
   plugins: [ [ AFrame.Plugin, {
       someConfigItem: 'someConfigValue'
   } ] ]
} );

Putting It All Together

Now we are going to instantiate an object with multple plugins, one plugin without configuration, one plugin with.

// Instantiate an object with multple plugins, one plugin without 
// configuration, one plugin with.
var obj = AFrame.AObject.create( {
   cid: 'SampleAObject',
   plugins: [ AFrame.FirstPlugin, [ AFrame.SecondPlugin, {
       someConfigItem: 'someConfigValue'
   } ] ]
} );

Reworking the "Add Friend" Example

A working example can be found on JSFiddle.

$( function() {

    // Instead of creating a model, create a SchemaConfig.
    // A Model in AFrame is an instance of data combined
    // with a Schema.  The schema config will be used when
    // creating the model.
    var friendSchemaConfig = {
        name: { type: 'text' }
    };

    // Our friends collection is an array.  Instead of binding
    // directly to an event on the collection, when creating
    // the list, we bind the list to the collection.
    // The ListPluginBindToCollection will take care of
    // updating of the list.
    var friendsCollection = AFrame.CollectionArray.create( {
        plugins: [ [ AFrame.CollectionPluginModel, {
             schema: friendSchemaConfig
        } ] ]
    } );

    // This is the friends list.  It is bound to the
    // friendsCollection, so any time a model is added or
    //  removed from the friends collection, the list will update.
    var friendsList = AFrame.List( {
        target: '#friendList',
        listElementFactory: function( model, index ) {
            return AFrame.DOM.createElement( 'li',
                model.get( 'name' ) );
        },
        plugins: [ [ AFrame.ListPluginBindToCollection, {
             collection: friendsCollection
        } ] ]
    } );

    // we insert into the friendsCollection once we
    // have a name.  The list will be updated automatically.
    $( '#add-friend' ).click( function( event ) {
           var friend_name = prompt("Who is your friend?");
           // A new model will be created when adding
           // to the friend collection.
           friendsCollection.insert( { name: friend_name } );
    } );
} );

The original post with updated examples is at: AFrameJS Tutorial – A Response to “Backbone.js Tutorial – by noob for noobs”