3.0 beta 2

Migrations

ActiveWidgets 3.0 is a major new release of the ActiveWidgets library. It is based on the new architecture resulted from the several years of research and design work done since version 2.0 was completed in 2006. The new library is smaller, faster and allows to do much more with less efforts. Unfortunately, it was not possible to achieve that without breaking compatibility with the previous version. The new library has a new API, which is not backwards compatible with version 2.

At the moment ActiveWidgets 3 is better suited for the new projects as converting code written for version 2.x may require significant efforts. To make it less painful ActiveWidgets 3 will be able to run side-by-side with version 2.x and at some point will introduce a compatibility layer (2.x API on top of 3.x) to simplify code migration.

Running 3.0 and 2.x simultaneously

It should be possible to run version 3.x and 2.x side-by-side, i.e. load both libraries into the same page and use components from both libraries at the same time. The libraries are using different namespaces and different css prefixes and should not produce any conflicts.

Compatibility layer

To simplify the migration of the code written for version 2.x there is a plan to build a compatibility layer - 2.x API implemented on top of 3.x library.

The compatibility layer will not be available at day 1 (at the time of 3.0 release). The initial focus will be to make version 3.0 fully functional, stable and well documented. Depending on the successful first stage, the compatibility layer may come together with version 3.1 (6-12 months after 3.0).

Main changes since version 2.x

The API and internal architecture of ActiveWidgets 3.0 differs significantly from the version 2. Here are the most important changes.

Data binding and reactive templates

The library is implemented from the bottom up with html templates, starting from the AX.HTML object itself -

var outerHTML = AX.template('<{{@tag}}{{@attributes}}>{{@innerHTML}}</{{@tag}}>');

The templates allow references to the data attributes as well as elements of the component tree (view model).

var panel = new AX.Panel({

    // external data
    data: {
        productName: 'XYZ-123-1',
        productDescription: 'Lorem ipsum...'
    },

    // button component
    reloadButton: {
        component: 'button',
        text: 'Reload',
        command: 'reloadProductData'
    },

    // content template
    html: '<div>Name: {{$productName}}</div>' +
          '<div>Description: {{$productDescription}}</div>' +
          '<div>{{@reloadButton}}</div>';
});

panel.reloadProductData = function(){
    this.data($.getJSON('product/1')); 
};

The ActiveWidgets templates are reactive, i.e. changes in the data or component tree trigger automatic updates of the underlying HTML markup.

Properties and initialization

ActiveWidgets objects can now be initialized with a single config object passed into constructor or set() method.

var button = new AX.Button({
    id: 'button1',
    width: 200,
    text: 'OK'
});

The config structure allows not only to initialize existing properties, but also creating new ones (if the property with the given name does not exist yet, it will be created automatically). This also applies to creating child objects (the type of the new child object can be provided via special component attribute). This way the whole composite component or component subtree can be created/initialized from a single JSON structure.

The JSON config can be assigned asynchronously, meaning that the whole config structure can come from the server side either from a static JSON file or generated by the server-side code.

// load panel config using jQuery AJAX
var config = $.getJSON('my-panel.json');

// initialize panel, create child objects and content
panel.set(config);

With ActiveWidgets 3 the majority of the user interface can be built using declarative style (JSON config for the interactive components, HTML templates for the static content and layout). This allows to minimize the amount of javascript code, achieve an optimal separation between data, presentation and UI behavior, and, in the future, implement interactive screen builder tools.

Each property can still be accessed directly via its own method. Instead of separate getter and setter methods (getValue(), setValue(x)) the library now generates a single accessor method (jQuery style) -

var x = obj.value(); // no arguments - get value
obj.value(123); // single argument - set value

Multiple inheritance (mixins)

ActiveWidgets 3 encourages the use of multiple inheritance (mixins). Instead of trying to build comprehensive inheritance hierarchy with every feature included by default, the library is made around small core and the set of plugins (mixins).

The plugin API is extremely simple. Each plugin is essentially just a normal class. It can be applied to any object by calling use() method.

var panel = new AX.Panel({

    // add optional features
    use: ['title', 'toolbar', 'status'],

    // configure new properties
    title: 'Composite panel', 
    toolbar: [item1, item2, item3],
    status: 'ok'
});

Composite controls, layouts and docking

The new library adds several ways to assemble individual objects into composite components. On the lowest level one can just use a template referencing child objects or object properties.

var composite = new AX.HTML({

    icon: {...},
    text: {...},

    innerHTML: '{{@icon}} {{@text}}'
});

Another option is to use AX.Component docking feature, allowing to place objects around the main content.

var component = new AX.Component({

    icon: {...},
    text: {...},

    dock: {left: ['@icon']},
    html: '{{@text}}'
});

And also AX.Container class allows to define its content as a collection of objects or references to the child objects.

var container = new AX.Container({

    icon: {...},
    text: {...},

    items: ['@icon', '@text']
});

Async processing and new data sources

ActiveWidgets 3 relies on javascript promises to simplify asynchronous data loading and processing. Promises can be assigned to any object property and the object will automatically handle success and failure conditions, including customizable progress and error state propagation and reporting.

// asynchronously load the page content
var content = $.get('my-page.html');

// assign deferred value to the panel property
panel.html(content);

ActiveWidgets is compatible with third-party promises libraries (including jQuery AJAX) while its own data source objects expose extended API to simplify asynchronous data processing.

// configure remote data proxy
var json = new AX.Proxy(...);

// load data record and extract a single field (asynchronously)
var text = json.load('products', {id: 123}).get('productDescription');

// assign deferred result to the component property
component.html(text);

ActiveWidgets new data source objects support both client-side and server-side operations.

jQuery integration

ActiveWidgets 3.0 does not have external dependencies and does not require jQuery. However if jQuery is already present on the page then ActiveWidgets will additionally expose its components via jQuery plugin api. In this case you can work with ActiveWidgets objects and third party jQuery plugins using similar syntax.

// create AX.Button instance as jQuery plugin
$('#button1').ax({
    component: 'button',
    margin: [10, 50],
    icon: 'home',
    text: 'Button 1'
});