The FlexJS DataGrid demonstrates the composition direction of FlexJS. The DataGrid is composed of a ButtonBar component (to act as the header row) and a set of List components for the columns. The lists are kept in a Container with a ScrollableViewport so they scroll together. The DataGrid keeps selections synchronized between the lists.
A typical DataGrid declaration in an application would be:
<js:DataGrid id="dataGrid" width="100%" height="100%" className="MyDataGrid" rowHeight="60"> <js:beads> <js:ConstantBinding sourceID="applicationModel" sourcePropertyName="productList" destinationPropertyName="dataProvider" /> </js:beads> <js:columns> <js:DataGridColumn label="First" dataField="image" itemRenderer="products.ImageItemRenderer"/> <js:DataGridColumn label="Second" dataField="title" /> <js:DataGridColumn label="Third" dataField="sales"/> </js:columns> </js:DataGrid> |
The ConstantBinding bead associates the application model's productList data with the dataProvider property of the DataGridModel. Each column of the DataGrid is defined by the DataGridColumn element, giving a title to the column and identifying the field within the dataProvider to use for the column. Optionally, a DataGridColumn can specify a custom itemRenderer (the one here displays an image) and set a specific width (not shown) for the column.
In addition to the ConstantBinding bead, the DataGrid uses other beads internally, as identified by the DataGrid style declaration in the defaults.css file:
DataGrid
{
IDataGridPresentationModel: ClassReference("org.apache.flex.html.beads.models.DataGridPresentationModel");
IBeadView: ClassReference("org.apache.flex.html.beads.DataGridView");
IBeadModel: ClassReference("org.apache.flex.html.beads.models.DataGridModel");
IItemRendererClassFactory: ClassReference("org.apache.flex.core.ItemRendererClassFactory");
IItemRenderer: ClassReference("org.apache.flex.html.supportClasses.StringItemRenderer");
background-color: #FFFFFF;
}
|
IDataGridPresentationModel. This is not an actual "model" bead but does describe the data needed to present the DataGrid. This includes the labels for each column and the height of each row. Other presentation models could include column widths, sort order, or anything else you might need.
IBeadView: This bead assembles the user interface out of a ButtonBar and Lists (one per column). The DataGridPresentationModel's array of column labels is the dataProvider for the ButtonBar. A List is created for each of those labels and all of the Lists share the same dataProvider as the DataGrid.
IBeadModel: This bead contains the dataProvider used by the lists. Applications use a binding bead (e.g., ConstantBinding) to map the application's data model to the DataGridModel.
IItemRendererClassFactory: This bead is used to generated instances of the itemRenderer for each list.
IItemRenderer: This bead names the default class to use for itemRenderers in the list. This can be overridden by the itemRenderer property of the DataGridColumn.
public function DataGridLinesBead()
{
// Set default separator line stroke.
var lineStroke:SolidColorStroke = new SolidColorStroke();
lineStroke.color = 0x333333;
lineStroke.alpha = 1.0;
lineStroke.weight = 1;
stroke = lineStroke;
}
|
public function set strand(value:IStrand):void
{
_strand = value;
_overlay = new GraphicsContainer();
IEventDispatcher(_strand).addEventListener("beadsAdded", handleBeadsAdded);
}
|
private function handleBeadsAdded(event:Event):void
{
var host:UIBase = _strand as UIBase;
var n:int = host.numElements;
for (var i:int=0; i < n; i++) {
var child:UIBase = host.getElementAt(i) as UIBase;
if (child.id == "dataGridListArea") {
_area = child;
_area.addElement(_overlay);
break;
}
}
// Now set up listeners to handle changes in the size of the DataGrid.
IEventDispatcher(_strand).addEventListener("sizeChanged", drawLines);
IEventDispatcher(_strand).addEventListener("widthChanged", drawLines);
IEventDispatcher(_strand).addEventListener("heightChanged", drawLines);
// Also set up a listener on the model to know when the dataProvider has
// changed which might affect the number of rows/columns and thus the
// grid lines.
var model:IBeadModel = _strand.getBeadByType(IBeadModel) as IBeadModel;
IEventDispatcher(model).addEventListener("dataProviderChanged", drawLines);
}
|
private function drawLines(event:Event):void
{
var sharedModel:IDataGridModel = _strand.getBeadByType(IBeadModel) as IDataGridModel;
var presentationModel:DataGridPresentationModel = _strand.getBeadByType(DataGridPresentationModel) as DataGridPresentationModel;
var layoutParent:ILayoutHost = _area.getBeadByType(ILayoutHost) as ILayoutHost;
var contentView:IParentIUIBase = layoutParent.contentView as IParentIUIBase;
var columns:Array = sharedModel.columns;
var arrayList:ArrayList = sharedModel.dataProvider as ArrayList;
var rowHeight:Number = presentationModel.rowHeight;
var totalHeight:Number = arrayList.length * rowHeight;
var columnWidth:Number = _area.width / columns.length;
// translate the stroke to a fill since rectangles are used for the grid
// lines and not lines.
var lineFill:SolidColor = new SolidColor();
var weight:Number = 1;
lineFill.color = (stroke as SolidColorStroke).color;
lineFill.alpha = (stroke as SolidColorStroke).alpha;
weight = (stroke as SolidColorStroke).weight;
_overlay.fill = lineFill;
columnWidth = (columns[0] as DataGridColumn).columnWidth;
var xpos:Number = isNaN(columnWidth) ? _area.width / columns.length : columnWidth;
_overlay.removeAllElements();
// draw the verticals
for (var i:int=1; i < columns.length; i++) {
_overlay.drawRect(xpos, 0, weight, totalHeight);
columnWidth = (columns[i] as DataGridColumn).columnWidth;
xpos += isNaN(columnWidth) ? _area.width / columns.length : columnWidth;
}
var n:int = arrayList.length;
// draw the horizontals
for (i=1; i < n+1; i++) {
_overlay.drawRect(0, i*rowHeight, _area.width, weight);
}
}
|
<js:DataGrid id="dataGrid" width="100%" height="100%" className="MyDataGrid" rowHeight="60">
<js:beads>
<beads1:DataGridLinesBead>
<beads1:stroke>
<js:SolidColorStroke color="#FF0000" />
</beads1:stroke>
</beads1:DataGridLinesBead>
<js:DataProviderChangeNotifier sourceID="applicationModel" propertyName="productList" />
<js:ConstantBinding
sourceID="applicationModel"
sourcePropertyName="productList"
destinationPropertyName="dataProvider" />
</js:beads>
<js:columns>
<js:DataGridColumn label="First" dataField="image" itemRenderer="products.ImageItemRenderer"/>
<js:DataGridColumn label="Second" dataField="title" />
<js:DataGridColumn label="Third" dataField="sales"/>
</js:columns>
</js:DataGrid>
|