s:CheckBox - getting selected value - actionscript-3

<fx:Script>
<![CDATA[
protected function button1_clickHandler(event:MouseEvent):void
{
if (cbAlwaysOnTop.selected) { // <<<<<< I get the error #1009 here
} else {
}
}
]]>
</fx:Script>
<mx:TabNavigator x="0" y="0" width="100%" height="100%">
<s:NavigatorContent label="Translate" width="100%" height="100%">
<s:Button label="test" click="button1_clickHandler(event)"/>
</s:NavigatorContent>
<s:NavigatorContent label="Settings" width="100%" height="100%">
<s:CheckBox x="10" y="22" label="always on top" selected="true" click="checkbox1_clickHandler(event)" id="cbAlwaysOnTop"/>
</s:NavigatorContent>
</mx:TabNavigator>
When I press the button I get the error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
What am I doing wrong?
It works if I first switch to the 2nd tabpage and then back and press the button.

You are probably in the wrong context and not have a reference to cbAlwaysOnTop.
Where is your button and where do you have the handling code?
Edit: ah, with your comment on the bottom I think I know what's going on, seems that NavigatorContent is only creating its contents when you navigate there, so if you try to access the CheckBox inside without first opening the tab, it hasn't been created and throwing you a null reference error.
Since I guess you want the settings to persist, the solution would be to create a PresentationModel class and bind the CheckBox value, so you can both save it between sessions and retrieve without relying on a UI element. Read this great article to understand what you need to do: http://riarockstars.com/2011/03/16/presentation-model-and-multiple-screens-part-1/

Ok, I found an easy solution to this using:
creationPolicy="all"
Using this in:
<mx:TabNavigator id="x1" x="0" y="0" width="100%" height="100%" creationPolicy="all">
would solve the problem.

Related

Items in DataGrid not initialized as expected

I seem to have a problem of items not being created as expected, resulting in event-listeners not being fired.
I am using a DataGrid column of checkboxes as seen here:
<mx:DataGrid id="gridComponents" height="100%">
<mx:columns>
<fwctrl:DataGridCheckBoxColumn id="colChkBox" width="20" selectionChanged="onGridChbBoxChange(event)" />
<mx:DataGridColumn headerText="Components" dataField="name" width="250"/>
</mx:columns>
</mx:DataGrid>
(fwctrl is the namespace of an internal library.)
And here is what the mxml of fwctrl:DataGridCheckBoxColumn looks like:
<mx:DataGridColumn xmlns:mx="http://www.adobe.com/2006/mxml" resizable="false" xmlns:grid="fwctrl.grid.*" xmlns:CheckBoxColumn="fwctrl.grid.CheckBoxColumn.*">
<mx:Metadata>
[Event(name="selectionChanged", type="fwctrl.grid.CheckBoxColumn.DataColumnCheckBoxEvent")]
</mx:Metadata>
<mx:Script>
<![CDATA[
...
]]>
</mx:Script>
<mx:headerRenderer>
<mx:Component>
<CheckBoxColumn:CheckBoxHeaderRenderer textAlign="center" click="checkboxheaderrenderer1_clickHandler(event)">
<mx:Script>
...
</mx:Script>
</CheckBoxColumn:CheckBoxHeaderRenderer>
</mx:Component>
</mx:headerRenderer>
<mx:itemRenderer>
<mx:Component>
<mx:Box horizontalAlign="center"
verticalAlign="middle" enabled="{outerDocument.isEnabled}">
<mx:Script>
<![CDATA[
...
protected function checkBox_initializeHandler(event:FlexEvent):void
{
trace("init checkbox");
}
]]>
</mx:Script>
<mx:CheckBox id="checkBox" click="onCheckBoxClick()" change="onChange(event)" initialize="checkBox_initializeHandler(event)"/>
</mx:Box>
</mx:Component>
</mx:itemRenderer>
CheckBoxHeaderRenderer is a class that inherits from checkbox.
using the mxml above I bind an ArrayCollection to the data provide by doing: gridComponents.dataProvider = coll;
Having the checkBox_initializeHandler event bound, I expect to see a message printed for each element in my collection.
In reality, the message will only be displayed for element that don't "fall off the grid", i.e. if there is a scroll bar (due to a lot of items being rendered), the items that are below the bottom of the grid (i.e. the ones that need to be scrolled to) will not print a message.
This also means that they are not created correctly and that the click="onCheckBoxClick()" is not hooked correctly and that onCheckBoxClick() does not get triggered.
Why is this happening and how can I fix this?
In Flex, itemRenderers aren't created on a one-to-one basis with your underlying data collection. You only get enough instances to display one screen's worth of data, and those instances get reused as you scroll.
To handle this in your code, refactor so that your click handler in the itemRenderer updates a property in your dataCollection (e.g. data.foo = true;).

Flex 4.x accordion items child unknown in actionscript

I have an Accordion component in Flex that has two children,
at the load of my page, I want to give the textvalue of a textfield in the first children to a textfield in the second children by using actionscript, but its faild
nb : when I click the secode children and I return to pass the textvalue from the first children, the action succeed!
<mx:HBox width="100%" height="310" horizontalAlign="center">
<mx:Accordion id="accordion1" width="100%" height="310" historyManagementEnabled="true">
<!-- child 1--><mx:VBox id="theme_resultat" width="95%" height="95%"
label="Résultat" horizontalAlign="center"
verticalAlign="middle">
<s:HGroup left="0" right="0" bottom="0" width="98%"
horizontalAlign="right">
<s:TextInput id="doc"/>
<mx:Button id="btnAdd" label="Add"
click="add_text(event)"
icon="#Embed('assets/images/add.png')"
paddingLeft="3" paddingRight="3"/>
</s:HGroup>
</mx:VBox>
<!-- child 2--><mx:VBox id="theme_detail" width="95%" height="95%" label="Détail"
verticalAlign="middle">
<mx:VBox width="100%" height="150" horizontalAlign="center">
<s:HGroup>
<mx:FormItem label="Titre:" paddingLeft="5">
<mx:TextInput id="doc_titre"/>
</mx:FormItem>
</s:HGroup>
</mx:VBox>
</mx:VBox>
</mx:Accordion>
</mx:HBox>
protected function add_text(event:MouseEvent):void
{
accordion1.selectedIndex=1;
doc_titre.text = doc.text;
}
}
when I click add I move to the second child, but the (mx:TextInput id="doc_titre") dont have the value of (s:TextInput id="doc"/)
for the second time I return to the child 1 and I click add, then I move to the second child and I find the value of (s:TextInput id="doc") in (mx:TextInput id="doc_titre")
What happens exactly? I think your problem may be caused by the fact that the components on the second children are not created until that view is opened, There are many solution for this, you could write some code in the creation complete oof the second view that will load the correct value, you can use databinding to bind the text inputs to the same string or you can try setting creationPolicy to all.
My answer is based on my above assumption so if I am wrong please give more details.
Check this http://help.adobe.com/en_US/flex/using/WS2db454920e96a9e51e63e3d11c0bf69084-7cb8.html#WS2db454920e96a9e51e63e3d11c0bf69084-7ae5 and try setting the creationPolicy to all then let us know if the problem is solved
Use createDefferedContent() instead:
for (var i:int = 0; i < accordion.numChildren; i++)
{
(accordion.getElementAt(i) as NavigatorContent).createDeferredContent();
}
This method creates the children and their components in the background. Don't use creationPolicy as I did since this causes memory-related issues.

How to change the visibility of components from different states in Flex 4

My goal is to change the visibility of a component from another component which is in another state. I been reading about the event but I can Flex it to work, I get this TypeError: Error # 1009: Can not access a property or method of a null object reference.
<<fx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.events.FlexEvent;
protected function buttonChange_clickHandler(event:MouseEvent):void
{
Tab.selectedIndex=1;
border.visible=true;
border.setStyle("backgroundColor",'#8000FF');
}
]]>
</fx:Script>
<mx:TabNavigator x="197.7" y="147.35" width="514" id="Tab" height="335">
<s:NavigatorContent label="State 1" width="100%" height="100%">
<s:Button x="65" y="103" id="buttonChange" label="Change state" click="buttonChange_clickHandler(event)" />
</s:NavigatorContent>
<s:NavigatorContent label="State2" id="state2" width="100%" height="100%">
<s:BorderContainer x="191" y="37" width="249" height="223" visible="false" cornerRadius="20" borderWeight="5" id="border">
</s:BorderContainer>
</s:NavigatorContent>
</mx:TabNavigator>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
The error occurs because your BorderContainer is not "created" when the tab navigator change the index. There are two fast ways to resolve that:
1) Use callLater to ensure that the border will be created when the tab change:
protected function buttonChange_clickHandler(event:MouseEvent):void
{
Tab.selectedIndex=1;
callLater(turnVisible);
}
private function turnVisible():void{
border.visible=true;
border.setStyle("backgroundColor",'#8000FF');
}
2) Or set the creationPolicy to "all" of the second </s:NavigatorContent>. That way will increase the startup time of the application:
<s:NavigatorContent label="State2" id="state2" width="100%" height="100%" creationPolicy="all">

Detect when object really removed from stage

I want to detect whether object was definitely removed from stage. I check many answers here and in other places & do not know how to be noticed that object was really removed from stage (i mean it is no longer displayed on the stage).
The code below is my last test:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Canvas width="100%" height="50%" backgroundColor="gray" id="c1">
<mx:Canvas id="cChild" backgroundColor="black" width="20" height="20"
left="20" top="20"
removedFromStage="trace('removed from stage ' + event.target)"
removed="trace('removed ' + event.target)">
</mx:Canvas>
</mx:Canvas>
<mx:Canvas width="100%" height="50%" backgroundColor="white" id="c2">
</mx:Canvas>
<mx:Button label="add child" click="c2.addChild(c1)" />
<mx:Button label="add child2" click="addChild(c1)" />
</mx:Application>
I do not understand what i found at console output:
removed MainFlex0.c1.cChild.border
- before click 'add child'
removed from stage MainFlex0.c1.cChild
removed MainFlex0.c2.c1.cChild.border
- after click 'add child', before 'add child2'
removed from stage MainFlex0.c2.c1.cChild
removed MainFlex0.c1.cChild.border
- after click 'add child2'
Is any condition i can check and be sure that object is REALLY "about to be removed from stage"?
Saram
removedFromStage is called just before the item is removed from the stage. If you don't do anything in that event handler the element will be removed.
if( !c1.stage ){
// it is not on stage
}

How to set current page dynamically in flexbook?

I am using a Flexbook which contains 2 BorderContainer. The code is shown below
<controls:FlexBook id="book" x="20" y="20"
width="100%" height="100%" horizontalCenter="0"
animateCurrentPageIndex="true"
showCornerTease="true" animatePagesOnTurn="true"
activeGrabArea="edge"
edgeAndCornerSize="20"
hardbackPages="false"
hardbackCovers="false"
pageShadowStrength="1"
curveShadowStrength="1"
pageSlope="0"
itemSize="page"
backgroundColor="0xC3D1D9"
borderThickness="0"
borderColor="0xC3D1D9"
cover="{null}"
backCover="{null}"
showPageSlopeAtRest="false"
cacheAsBitmap="true">
<s:BorderContainer id="page1">
<mx:ColumnChart x="0" y="35" id="ccMain" height="90%" width="99%"
cacheAsBitmap="true"
showDataTips="true" dataTipFunction="{getDataTip}" type="clustered" backgroundElements="{bge4}">
<!-- column chart code goes here -->
</mx:ColumnChart>
</s:BorderContainer>
<s:BorderContainer id="page2" creationComplete="productMainPg2.addElement(lineChart)">
<mx:Legend dataProvider="{lineChart}" height="21" x="10" width="95%" color="#b1b7f4"/>
</s:BorderContainer>
This code shows page1 as current page. I want to show the BorderContainer (id= page2) as my current page dynamically on a button click. I tried setting currentPageIndex = 1, but I get a blank page by doing this.
Create a [Bindable] boolean property (i.e. [Bindable] public var isShowingFirstPage:Boolean = true)
Set the BorderContainer's "visible" and "includeInLayout" properties to be contingent on this value. (i.e. ...id="page1" visible="{isShowingFirstPage:Boolean}" includeInLayout="{isShowingFirstPage:Boolean}... for the first one, and ...id="page2" visible="{!isShowingFirstPage:Boolean}" includeInLayout="{!isShowingFirstPage:Boolean}...for the second)
toggle / change that boolean based on some input, user gesture, business logic, whatever and the two container's should display / update accordingly.