Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: changed namespaces

...

To make life easier on yourself, use the same package names that the FlexJS framework uses. That way your cade code can move into the framework repository with little change.

Your "component" should live in: org.apache.flex.html.staticControls. The beads that make up your component should live in: org.apache.flex.html.staticControls.beads or one of its sub-directories, depending on its purpose.

FlexJS assembles a component from its beads through the use of the ValuesManager and style sheet. The ValuesManager class looks for your component in the defaults.css style sheet and picks up the class reference for your view and model beads. These beads will be instantiated for your component and added to its strand.

Component Example

...

For more details about creating components, see Creating Components. The code shown in the example is not intended to be a true component and a number of items have been left out; it is for illustrative purposes only.

Consider a horizontal version of the NumericStepper where there is a Label showing a value and a Button to decrement the value to the left of the Label and a Button to increment the value to the right of the Label. This is a composite component and will be easy to cross-compile to JavaScript.

The component is called, "NumericAdjustment", or org.apache.flex.html.staticControls.NumericAdjustment. This component needs the following beads:

...

NumericAdjustment {
iBeadView: ClassReference("org.apache.flex.html.staticControls.beads.NumericAdjustmentView");
iBeadModel: ClassReference("org.apache.flex.html.staticControls.beads.models.NumericAdjustmentModel");
}

The NumericAdjustment component class, org.apache.flex.html.staticControls.NumericAdjustment, has very little content of its own:

/**
* The event dispatched whenever the value of the component changes.
*/
[Event("change")]
/**
* The NumericAdjustment component displays a value with increment and decrement buttons.
*
* @langversion 3.0
* @playerversion Flash 10.2
* @playerversion AIR 2.6
* @productversion FlexJS 0.0
*/ 
public class NumericAdjustment extends UIBase {
/**
* The current value of the component
*
* @langversion 3.0
* @playerversion Flash 10.2
* @playerversion AIR 2.6
* @productversion FlexJS 0.0
*/
public function get value():Number {
return NumericAdjustmentModel(model).value;
}
public function set value(oldValue:Number):void {
NumericAdjustmentModel(model).value = oldValue;
}
}

 

The component class has [Event] metadata to indicate that the component can dispatch change events and declares a value property. Notice that the property is not stored in the component itself but in the component's model. The model property is part of the base class, UIBase.NOTE: the

The first time the model property is accessed, the framework code fetches the model's class definition from the style sheet and instantiates and instance of it.

The NumericAdjustmentModel bead has a single property, value, which holds the value for the component:

/**
* The NumericAdjustmentModel class holds the data model for the NumericAdjustment component.
*
* @langversion 3.0
* @playerversion Flash 10.2
* @playerversion AIR 2.6
* @productversion FlexJS 0.0
*/
public class NumericAdjustmentModel implements IBeadModel {
 private var _strand:IStrand;
/**
*  @copy org.apache.flex.core.IBead#strand
*  
*  @langversion 3.0
*  @playerversion Flash 10.2
*  @playerversion AIR 2.6
*  @productversion FlexJS 0.0
*/
public function set strand(value:IStrand):void {
   _strand = value;
}

private var _value:Number;
/**
* The current value of the component
*
* @langversion 3.0
* @playerversion Flash 10.2
* @playerversion AIR 2.6
* @productversion FlexJS 0.0
*/
public function get value():Number {
   return _value;
}
public function set value(newValue:Number):void {
if( _value != newValue) {
_value = newValue;
IEventDispatcher(_strand).dispatchEvent(new Event("change"));
}
}
}

Whenever the value in model changes, the model dispatches a change event using the strand (cast to IEventDispatcher).

The NumericAdjustmentView bead has a little more work to do. Most of the set up is done when the bead has been assigned its strand:

/**
* The NumericAdjustmentView class is a bead that creates the elements of the NumericAdjustment component.
*
* @langversion 3.0
* @playerversion Flash 10.2
* @playerversion AIR 2.6
* @productversion FlexJS 0.0
*/
public class NumericAdjustmentView implements IBeadView {
 private var _strand:IStrand;

/**
*  @copy org.apache.flex.core.IBead#strand
*  
*  @langversion 3.0
*  @playerversion Flash 10.2
*  @playerversion AIR 2.6
*  @productversion FlexJS 0.0
*/
public function set strand(value:IStrand):void {
   _strand = value;

_leftButton = new Button();
_leftButton.text = "-";
_strand.addElement(_leftButton);
_leftButton.addEventListener("click",handleDecrement);

_label = new UILabel();
_label.text = "";
_strand.addElement(_label);

_rightButton = new Button();
_rightButton.text = "+";
_strand.addElement(_rightButton);
_rightButton.addEventListener("click",handleIncrement);

IEventDispatcher(_strand).addEventListener("change",handleChange);

sizeAndPosition(null);
}

/**
* @private
*/
private function sizeAndPosition(event:Event):void
{
//TODO: put the components in order: incr button, label, decr button
}

/**
* @private
*/
private function handleChange(event:Event):void {
   var model:NumericAdjustmentModel = _strand.getBeadByType(IBeadModel) as NumericAdjustmentModel;
_label.text = String(model.value);
}

/**
* @private
*/
private function handleDecrement(event:Event):void {
var model:NumericAdjustmentModel = _strand.getBeadByType(IBeadModel) as NumericAdjustmentModel;
model.value -= 1;
}

/**
* @private
*/
private function handleIncrement(event:Event):void {
var model:NumericAdjustmentModel = _strand.getBeadByType(IBeadModel) as NumericAdjustmentModel;
model.value += 1;
}
};

The view bead creates the component elements (buttons and label). It also listens for a change event that the model will dispatch when the value changes. Doing it this way, rather than from the code that changes the model (the handleDecrement and handleIncrement functions), allows  the component to updated by anything that changes its model - which could be some other component.NOTE:

The view bead should also listen for changes to the strand's width and height (you'll have to cast the strand to the UIBase class) and size and position the two buttons and label using the sizeAndPosition() function as the event listener.

Putting it Together

Once you have the component's strand and beads ready, you can test them in your sample application by putting them into  your initial UIView component.

After you have it working in ActionScript, you can quickly test it in JavaScript by cross-compiling it. The FalconJX compiler will build JavaScript versions of all of your component pieces. You can find them in the bin/js-debug (and bin/js-release) directory in the same directory/package path. Opening the bin/js-debug/index.html file in a browser should result in an HTML page that works  exactly like the Flash SWF version.

Do not forget to include asdoc tags in your component as shown in the example code above. 

When your component is ready to become part of the framework, it can go into the FlexJSJX project if the component can be  100% cross-compiled into JavaScript. If you had to create any part of it in JavaScript, or modify any of the generated JavaScript files to get the component to work, then the ActionScript code must be placed into the FlexJSUI project.

...