Child pages
  • Creating Components

This documentation is currently being moved to our new documentation site.

Please view or edit the documentation there, instead.

If you're looking for Fluid Project coordination, design, communication, etc, try the Fluid Project Wiki.

Skip to end of metadata
Go to start of metadata
On This Page

An application created using the Infusion Framework will be a collection of individual components. This page provides guidelines that will help you to create components that

  • function optimally with the Infusion Framework,
  • take full advantage of Framework features, and
  • are easy to maintain.

Use declarative configuration whenever possible

The Infusion Framework is designed to minimize the amount of actual code you have to write. Most of your component definitions will be declarative, in the form of JSON blocks defining defaults for your components.

These declarative blocks should be used to do almost everything, including

  • defining relationships between components
  • attaching methods to components
  • firing events

The small amount of code you will write should be in free functions that will be referenced by the defaults.

Define components to be 'autoInit'

Components should always be declared as "autoInit" by including the designation in the gradeNames option:

fluid.defaults("my.component", {
    gradeNames: ["my.grade", "fluid.rendererComponent", "autoInit"],
    ....
});

In a future release of the Framework, this will become the default and it will not need to be specified explicitly, but for now, you must include this string.

Use events declaratively

Wherever possible, use event boiling instead of firing events manually using the fire() function. If a component needs to know when something happens in one of its subcomponent, declare the parent event as a listener for the child's event:

/* The subcomponent defines an event that will fire at some point */
fluid.defaults("my.component.kid", {
    ...
    events: {
        childEvent: null
    }
});

/* The root component declares an event that becomes a listener for the subcomponent's event */
fluid.defaults("my.component", {
    ...
    events: {
        myEvent: null
    },
    components: {
        child: {
            type: "my.component.kid"
            listeners: {
                childEvent: "{parent}.myEvent"
            }
        }
    }
});

Add methods to a component using invokers or members

To add methods to a component, use invokers (sparingly) or members. Don't add them directly to 'that' in an init function (i.e. don't use "that.save = function () {...};).

The members option is essentially a simpler version of invokers. The right-hand side of each property is evaluated as an IoC expression and assigned to the top-level component path held on the left-hand side. Unlike invokers, methods are evaluated only once during component construction.

fluid.defaults("my.component", {
    ...
    members: {
        width: "{that}.options.width", // promotes the 'size' option to a property of the component, i.e. 'that.size'
        computeArea: "my.component.computeArea" // component method will resolve to the free function
    }
});

Define defaults in a consistent order

The core definition of a component is its 'defaults block', defined using a call to fluid.defaults(). The defaults block defines the type of component, the events it fires, its subcomponents, and other integrator-configurable options.

Since the defaults block is the main definition of what a component it, consistency in its form makes modifying code and debugging much easier. The Fluid community has developed a preferred ordering of items in the component defaults block. Maintaining this ordering will make it easier for anyone looking at the code to understand the component.

The following code snippet includes all possible contents of a defaults block in the recommended order. (Note that any given component will likely not include all of these properties.)

    fluid.defaults("my.component.name", {
    
        // gradeNames should always go first, so we know what "type" of component is being defined.
        gradeNames: ["fluid.rendererComponent", "autoInit"],
        
        // standard options for model-bearing components
        model: {},
        applier: ""
        
        // standard options for evented components
        events: {},
        listeners: {},
        
        // standard options for view components
        selectors: {},
        strings: {},
        styles: {},
        
        // standard options for renderer components 
        renderOnInit: true,
        selectorsToIgnore: [],
        repeatingSelectors: [],
        protoTree: {},  // mutually exclusive with produceTree
        produceTree: "",
        rendererFnOptions: {},
        rendererOptions: {},
        
        // templates, usually used with renderer components
        resources: {} // template
        
        // component specific options
        compOpt1: "",
        compOpt2: {},
        compOptETC: [],
        
        // component methods
        invokers: {},
        
        // child components
        components: {}
    });
  • No labels