Dynamically generated MXML data doesn't get rendered - actionscript-3

So I have a requirement to display dynamically generated data in the view.
For this, my idea was to create a mxml file and then use it as an object. Fill the data in the ibject and then use addChild to display it. But even after adding all the data. The dynamically generated mxml file doesn't gets displayed.
Code
BuyTogetherGrid.MXML
<?xml version="1.0" encoding="utf-8"?>
<mx:Box xmlns:mx="http://www.adobe.com/2006/mxml" width="80" height="60" xmlns:image="org.commodity.detail.image.*">
<mx:HBox>
<image:ImageBox id="buyTogetherImg"></image:ImageBox>
<mx:VBox id="textInfo">
<mx:Box id="commonNameBox">
<mx:Label id="commonName">
</mx:Label>
</mx:Box>
<mx:Box id="commonPriceBox">
<mx:Label id="commonPrice">
</mx:Label>
</mx:Box>
</mx:VBox>
</mx:HBox>
<mx:Script>
<![CDATA[
public function createGrid():void{
this.buyTogetherImg = new ImageBox();
this.commonName = new Label();
this.commonPrice = new Label();
}
]]>
</mx:Script>
</mx:Box>
This is my MXMl File. My idea was to create an object of this mxml object. Add data to buyTogetherImg, CommonName, CommonPrice and then use addChild
Part where I set the data
<mx:HBox id="buyTogetherBox" width="100%" borderColor="black">
</mx:HBox>
The upper HBox is the container where I will keep all my generated object
var buyTogetherBox : BuyTogetherGrid = new BuyTogetherGrid();
buyTogetherBox.createGrid();
for each(var item:cmListItem in commod.items){
if(item.dataFormat == 2){
buyTogetherBox.buyTogetherImg.imgData = item.value as ImageData;
} else if(item.dataFormat == 0){
buyTogetherBox.commonName.text = item.value.toString();
} else if(item.dataFormat == 3){
buyTogetherBox.commonPrice.text = StringUtil.numToStrPrice(item.value as Number);
}
}
this.buyTogetherBox.addChild(buyTogetherBox);
}
The code check some conditions and add the data. However the buyTogetherBox is not visible. But if I try something like
this.buyTogetherBox.addChild(buyTogetherBox.buyTogetherImg);
then i can see the image in the H:Box.
I am pretty new to Flex. so may be I would have missed something

You are leaving the statically created instances of the label and image control unused and creating new instances instead. Basically, the entire createGrid() function is unnecessary. You already have the controls created in MXML. Just use them with creating new instances.
var grid:BuyTogetherGrid = new BuyTogetherGrid();
grid.addEventListener(FlexEvent.CREATION_COMPLETE, this.grid_creationCompleteHandler);
Elsewhere in the same class...
private function grid_creationCompleteHandler(event:FlexEvent):void
{
// Set your properties here
}

As Pranav said it takes some time to create MXML components and if you try to assess them immediately you will get a null pointer exception because they don't exist yet. A quick and dirty solution is to make public variables in your BuyTogetherGrid.MXML and then bind the text properties to these variables, like
<?xml version="1.0" encoding="utf-8"?>
<mx:Box xmlns:mx="http://www.adobe.com/2006/mxml" width="80" height="60" xmlns:image="org.commodity.detail.image.*">
<fx:Script>
<![CDATA[
[Bindable] public var imageData:ImageData;
[Bindable] public var name:String;
[Bindable] public var price:String;
]]>
</fx:Script>
<mx:HBox>
<image:ImageBox id="buyTogetherImg" imgData={imageData}/>
<mx:VBox id="textInfo">
<mx:Box id="commonNameBox">
<mx:Label id="commonName" text="{name}">
</mx:Label>
</mx:Box>
<mx:Box id="commonPriceBox">
<mx:Label id="commonPrice" text="{price}">
</mx:Label>
</mx:Box>
</mx:VBox>
and then you do
buyTogetherBox.imageData = yourImageData;
buyTogetherBox.name = "Your Name";
buyTogetherBox.imageData = "Your price";
and yes, remove the unnecessary createGrid() method

Related

Group Element not working in adobe flex 3

i am trying to create multiple tab with close button in adobe flex 3. for this i have created parent and child object. parent object for tab and child object for close button and place both object in Group container grammatically in function called "addButton()". my code working fine in adobe flex 4.5 but not working in adobe flex 3. due to some reason i have to use adobe flex 3. i have try other container like: HBox, controllbar etc but these are unable to make proper tab view. below is code.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
minWidth="127" minHeight="34" backgroundColor="#F4E8E8">
<s:layout>
<s:FormItemLayout/>
</s:layout>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.graphics.SolidColor;
import spark.components.Button;
import spark.components.Group;
import spark.primitives.Rect;
public function addButton():void {
//Child Object
var myButton:Button = new Button();
myButton.id = "dd";
myButton.label="X";
myButton.width = 40;
myButton.height = 20;
myButton.depth =1;
myButton.x=50;
myButton.setStyle("color",'red');
myButton.addEventListener(MouseEvent.CLICK, btn);
//Parent Object
var lble:Group = new Group();
var solidColor:SolidColor = new SolidColor(0xFF0000);
var rec:Rect = new Rect();
rec.fill = solidColor;
rec.percentWidth = 100;
rec.percentHeight = 100;
lble.width = 127;
lble.height = 34;
lble.depth =0;
lble.addElement(rec);
lble.addEventListener(MouseEvent.CLICK, lable);
lble.addElement(myButton);
myGroup.addElement(lble);
}
private function btn(e:Event):void {
e.stopPropagation();
jj.text = 'Text For Button';
}
private function lable(e:Event):void {
kk.text = "Text For Label";
}
]]>
</fx:Script>
<s:HGroup id="myGroup">
<s:Button width="126" height="34" click="addButton();" label="Click" skinClass="spark.skins.spark.ButtonSkin"/>
</s:HGroup>
<s:Label id="jj" x="14" y="150" width="1200" height="50" backgroundColor="gray" text="Button"/>
<s:Label id="kk" x="14" y="69" width="1200" height="50" backgroundColor="gray" text="Label"/>
</s:Application>
please help me
1) Group Element (container) Not working in Flex 3 :
Definitely it won't work in Flex 3, there is major difference between Flex 3 and Flex 4 or mx(halo) and spark(Gumbo) respectively. You need to have clear understanding of both the things if you want to convert a component from spark to mx or vice versa.
Here is a nice article that explain the
Difference between Flex 3 and Flex 4
2) I am trying to create multiple tab with close button in adobe flex 3:
Since Flex is a 10 years matured framework there are plenty of open source components available out there you don't have to create a component from scratch. But i appreciate your attempt to do it on your own way.
Have a look in to this before you start creating components
Flex 3 Component Life cycle
Flex 4 Component Life cycle and Creating Advanced spark components
Spark Tab with close button
Flex 3 SuperTabNavigator FlexLib component
Flex: How to add a tab close button for TabNavigator component
You can use Box as mx component. Here is what you can do in flex 3:
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import mx.containers.Box;
public function addButton():void {
//Child Object
var myButton:Button = new Button();
myButton.id = "dd";
myButton.label="X";
myButton.width = 40;
myButton.height = 20;
myButton.x=50;
myButton.setStyle("color",'red');
myButton.addEventListener(MouseEvent.CLICK, btn);
//Parent Object
var box:Box = new Box();
box.setStyle("borderThickness", "1");
box.setStyle("borderStyle", "solid");
box.setStyle("borderColor", "black");
box.setStyle("backgroundColor", "0xFF0000");
box.width = 127;
box.height = 34;
box.addEventListener(MouseEvent.CLICK, lable);
box.addChild(myButton);
myHBox.addChild(box);
}
private function btn(e:Event):void {
e.stopPropagation();
jj.text = 'Text For Button';
}
private function lable(e:Event):void {
kk.text = "Text For Label";
}
]]>
</mx:Script>
<mx:HBox id="myHBox">
<mx:Button width="126" height="34" click="{addButton();}" label="Click"/>
</mx:HBox>
<mx:Label id="jj" x="14" y="150" width="1200" height="50" text="Button"/>
<mx:Label id="kk" x="14" y="69" width="1200" height="50" text="Label"/>
</mx:Application>

Actionscript Datagrid ItemEditor with different types than type of DataGridColumn value

I have a DataGrid where one column has a ComboBox as an item editor for one of the columns. The type of values in the ComboBox's dataProvider are different from the type of value that is stored in the cell being edited. How can I map the value returned by the item editor to the value in the cell. A complete example illustrating my problem:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
creationComplete="init()">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var items:ArrayCollection;
[Bindable]
public var foobar:ArrayCollection;
private function init():void
{
items = new ArrayCollection();
items.addItem({name : "Adam", abbrev: "ABCD"});
items.addItem({name : "Frank", abbrev : "EFGH"});
items.addItem({name:"Bob", abbrev:"ABCD"});
foobar = new ArrayCollection();
foobar.addItem({id:"ABCD", displayValue:"Adam Buys Cheap Drinks"});
foobar.addItem({id:"EFGH", displayValue:"Eban Flies Great Heat"});
}
]]>
</fx:Script>
<mx:DataGrid dataProvider="{items}" editable="true">
<mx:columns>
<mx:DataGridColumn headerText="Name" dataField="name" />
<mx:DataGridColumn headerText="Abbrev" dataField="abbrev"
editorDataField="selectedItem">
<mx:itemEditor>
<fx:Component>
<mx:ComboBox labelField="displayValue"
dataProvider="{outerDocument.foobar}" />
</fx:Component>
</mx:itemEditor>
</mx:DataGridColumn>
</mx:columns>
</mx:DataGrid>
</s:Application>
What I want to see happen is that when the user picks an item from the ComboBox, that the id attribute of the value returned is placed in the cell being edited in the grid.
As it stands the id/displayValue object is passed instead, resulting in [object object] being displayed.
In your case it will be enough to change editorDataField="selectedItem" to editorDataField="selectedLabel". If you want to have more complex itemEditor (for example, add some text automatically) than you can do next:
<mx:DataGridColumn headerText="Abbrev" dataField="abbrev">
<mx:itemEditor>
<fx:Component>
<mx:ComboBox labelField="displayValue"
dataProvider="{outerDocument.foobar}">
<fx:Script>
<![CDATA[
override public function get value():Object
{
return selectedLabel + "some example text";
}
]]>
</fx:Script>
</mx:ComboBox>
</fx:Component>
</mx:itemEditor>
</mx:DataGridColumn>
And last one - good article about itemEditors (most about it I took there).
In method get value you can return anything and this will be shown on DataGrid.
You need to create own item editor based on ComboBox class and implement property that will return id of selected item. Something like this:
public function get selectedItemId():String {
if (selectedItem) {
return selectedItem.id;
} else {
return null;
}
}
Then you should set this new property selectedItemId as editorDataField in DataGridColumn.

Get Properties of Adobe Flex Charts

I need to get all the properties of flex charts by using/calling the respective chart.
Example For Flex Area Chart we have xField,yField and minField.
Is there any way to get these properties from each chart through any methods.
There are no methods on the charts that will do this. If you want to find out the properties of the chart and their series, you will need to do this via reflection.
You can use the global describeType() method on any object for this. This will return you an XML object containing all properties of the object.
There is also an API on top of describeType that allows for easier access and introspection of objects: AS3Commons Reflect
Maybe this code will be useful, is an example for view all information of the ChartBase object:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" minWidth="955" minHeight="600" creationComplete="init()">
<mx:Script>
<![CDATA[
import mx.charts.chartClasses.ChartBase;
public function init():void{
getInfo(new ChartBase());
}
private function getInfo(obj:Object):void{
txt1.text = describeType(obj);
var myXML:XMLList = new XMLList(describeType(obj));
var info:String = "";
for each(var node:XML in myXML.children()){
switch(node.name().toString())
{
case "variable":
{
info = info + "var - " + node.#name + "\n"; //properties
break;
}
case "accessor":
{
info = info + "accessor - " + node.#name + "\n"; //getter-setter
break;
}
case "method":
{
info = info + "method - " + node.#name + "\n"; //methods
break;
}
}
txt2.text = info;
}
}
]]>
</mx:Script>
<mx:Label text="View Information of 'ChartBase' Object"/>
<mx:HBox width="100%">
<mx:HBox width="50%">
<mx:VBox width="100%" height="100%">
<mx:Label text="All Object Information"/>
<mx:TextArea id="txt1" width="800" height="800"/>
</mx:VBox>
</mx:HBox>
<mx:HBox width="50%">
<mx:VBox width="100%" height="100%">
<mx:Label text="Properties,Accessor and Methods from this Object"/>
<mx:TextArea id="txt2" width="800" height="800"/>
</mx:VBox>
</mx:HBox>
</mx:HBox>
</mx:Application>
Basically the method describeType returns a XML with the object information.
Adobe reference
Performing object introspection
Here you can run a SWF with this code LINK.

highlighting mx:datagrid individual cell on drag event

I'm new to flex and recently assigned a project where I need to work on datagrid to make it able to highlight individual or multiple (but adjacent) cells based on the item being dragged from a list. So scenario is like this...
I'm using flex SDK 4.6. I have a mx datagrid (I can't use spark or other version due to some restrictions) with some dates as rows and time (00-23 hrs) in columns( so total 25 columns: 1st column showing dates and rest 24 for hours).
That way we have each date acting as row-header which runs through 24 columns for hours. I have a list which is getting populated from an XML file and each item in the list has a date and time elements associated with it. when we drag an item from the list into datagrid, it should highlight particular cell(s) in the datagrid based on matching dates(from list item being dragged and datagrid dates column) and matching hours (from list item being dragged and datagrid hour columns).
So far I'm able to get the row index and column index/indices on drag enter but getting them highlighted as a whole row-column. for example if it turns out to be 3rd row and 4th-5th column, it highlights whole 3rd row(all 25 columns) and all cells under 4th-5th column. what I need is to get to a specific location like someCell(rowIndex:xx, ColIndex:YY) and change that cell's style. There are some examples with item-renderer but they are using cell's data to find if its less than or greater than some value and then maipulating it, but I couldn't use it in my case.
Secondly I want to replace the scrollbars with two buttons(one at top and another at bottom) of the dates column to scroll the dates. I'll be very thankful for any advise on that too.
Hope I've made the questions/scenario clear. Thanks for having a look into it. Looking forward for a helping hand from the community. This task is on urgent list...please help.
If I have understood your problem coorectly, here is my proposal.
You should be able to give to each cell of the datagrid information about date and time. You can make it through ItemRenderer, which implements IDropInListItemRenderer interface. If user selects any element of your XML List, he defines a certain time point, which should be compared with one of the ItemRenderer.
I hope it will help you.
//CellRenderer.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:HBox xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="100%" height="100%"
backgroundColor="{(cellDate == parentDocument.selectedDate && cellHour == parentDocument.selectedHour) ? 0xfcb9bb : 0xfefceb}"
implements="mx.controls.listClasses.IDropInListItemRenderer">
<fx:Script>
<![CDATA[
import mx.controls.dataGridClasses.DataGridListData;
import mx.controls.listClasses.BaseListData;
private var _listData:BaseListData;
[Bindable]private var cellDate:String;
[Bindable]private var cellHour:String;
override public function set data( value:Object ) : void
{
super.data = value;
cellDate = data.date;
cellHour = (listData as DataGridListData).label;
}
[Bindable]public function get listData() : BaseListData
{
return _listData;
}
public function set listData( value:BaseListData ) : void
{
_listData = value;
}
]]>
</fx:Script>
</mx:HBox>
//Application
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
layout="absolute"
minWidth="955" minHeight="600" creationComplete="initApp()" backgroundColor="0xeeeeee">
<fx:Declarations>
<fx:Model id="cells">
<dataset>
<data>
<date>14.01.2013</date>
<h00>00:00</h00>
<h01>01:00</h01>
<h02>02:00</h02>
<h03>03:00</h03>
</data>
<data>
<date>15.01.2013</date>
<h00>00:00</h00>
<h01>01:00</h01>
<h02>02:00</h02>
<h03>03:00</h03>
</data>
<data>
<date>16.01.2013</date>
<h00>00:00</h00>
<h01>01:00</h01>
<h02>02:00</h02>
<h03>03:00</h03>
</data>
<data>
<date>17.01.2013</date>
<h00>00:00</h00>
<h01>01:00</h01>
<h02>02:00</h02>
<h03>03:00</h03>
</data>
</dataset>
</fx:Model>
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.events.DragEvent;
import mx.events.ListEvent;
[Bindable]public var selectedDate:String;
[Bindable]public var selectedHour:String;
private function initApp():void
{
srclist.dataProvider = new ArrayCollection([
{activity: 'Reading', date: '14.01.2013', hour: '01:00'},
{activity: 'Television', date: '15.01.2013', hour: '03:00'},
{activity: 'Movies', date: '16.01.2013', hour: '02:00'}
]);
}
protected function onItemRollOver(event:ListEvent):void
{
var item:Object = (srclist.dataProvider as ArrayCollection).getItemAt(event.rowIndex);
selectedDate = item.date;
selectedHour = item.hour;
}
]]>
</fx:Script>
<mx:HBox x="35" y="28" height="200">
<mx:VBox width="124" height="100%">
<mx:Label text="Available Activities"/>
<mx:List
id="srclist"
labelField="activity"
width="118" height="100%"
allowMultipleSelection="false"
dragEnabled="true"
dragMoveEnabled="true" selectionColor="0xffffff"
itemRollOver="onItemRollOver(event)" itemRollOut="selectedDate = ''; selectedHour = '';"/>
</mx:VBox>
<mx:VBox height="100%">
<mx:Label text="Scheduler"/>
<mx:DataGrid
width="386" height="100%" dataProvider="{cells.data}"
alternatingItemColors="[0xffffff]"
horizontalGridLineColor="0x999999"
horizontalGridLines="true"
verticalGridLineColor="0x999999"
sortableColumns="false"
resizableColumns="false" selectable="false">
<mx:columns>
<mx:DataGridColumn dataField="date" headerText="Data"/>
<mx:DataGridColumn dataField="h00" headerText="00:00" itemRenderer="com.CellRenderer"/>
<mx:DataGridColumn dataField="h01" headerText="01:00" itemRenderer="com.CellRenderer"/>
<mx:DataGridColumn dataField="h02" headerText="02:00" itemRenderer="com.CellRenderer"/>
<mx:DataGridColumn dataField="h03" headerText="03:00" itemRenderer="com.CellRenderer"/>
</mx:columns>
</mx:DataGrid>
</mx:VBox>
</mx:HBox>
</mx:Application>

Updating view spark.components.List

I am using a List component inside an itemRenderer. The main user interaction involves dragging an item from the List in one renderer and dropping it in another.
My problem: When the data object is updated I want the Lists' height to be modified according to the number of objects in the dataprovider(dp), which is passed to the List from the data object. Now I have tried to invalidate the display of the List, refresh its dp and have tried putting this line assets.length > 0 ? assetList.percentHeight = 100 : assetList.height = 10; in other event handlers, such as dragdrop handlers, collection event handlers for the dp etc. I have also tried refreshing the dp for the List component that is using this renderer. The view does eventually get updated but only if I resize the list, or use the scroller or when I begin dragging a new List item but never after the drop.
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
autoDrawBackground="true" width="100%" creationComplete="init()" currentState="collapsed">
<fx:Script>
<![CDATA[
[Bindable] private var itemRenderer:ClassFactory;
[Bindable] private var colWidth:Number = 100;
[Bindable] private var assets:ArrayCollection = new ArrayCollection;;
public function init():void{
itemRenderer = new ClassFactory(DefaultRenderer);
this.addEventListener(FlexEvent.DATA_CHANGE, onDataChange);
}
private function onDataChange(e:FlexEvent):void {
assets = data.assets;
trace(data.name, assets.length);
assets.length > 0 ? assetList.percentHeight = 100 : assetList.height = 10;
}
]]>
</fx:Script>
<s:Group width="100%">
<s:layout>
<s:VerticalLayout gap="0" />
</s:layout>
<s:ToggleButton
id="viewToggle"
label="{data.name}"
width="100%"
height="50"
/>
<s:List id="assetList"
width="100%"
dataProvider="{assets}"
height = "10"
top="0" left="0" bottom="0" right="0"
dragEnabled="true"
allowMultipleSelection="true"
dragMoveEnabled="true"
dropEnabled="true"
itemRenderer="{itemRenderer}"
>
<s:layout>
<s:TileLayout requestedColumnCount="2"
horizontalGap="0" verticalGap="0"
columnWidth="{colWidth}" rowHeight="{colWidth}"/>
</s:layout>
</s:List>
</s:Group>
</s:ItemRenderer>
In your onDataChange method try this:
itemRenderer = null;
itemRenderer = new ClassFactory(DefaultRenderer);