Flex ItemRender Not Updating Data Source - actionscript-3

First up sorry the the mass of code and terrible coding, it's been some time since I have done AS3/Flex and for the life of me I can't remember how to get an ItemRenderer inside an ItemRender to update the data source. For example GymButton2.mxml simple adds +1 to the data it it provided with when a button is clicked and this should update the original datasource activeGym but... it doesn't and I assume this is because binding is not working as expected?
Main.mxml
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.events.FlexEvent;
[Bindable]
public var activeGym:Gym2;
]]>
</fx:Script>
<s:DataGroup x="33" y="56" width="200" height="200" dataProvider="{activeGym.sets}" itemRenderer="GymSetRenderer">
<s:layout>
<s:VerticalLayout />
</s:layout>
</s:DataGroup>
</s:WindowedApplication>
Gym2.as
package
{
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;
import mx.collections.ArrayCollection;
[Bindable]
public class Gym2 extends EventDispatcher
{
public var sets:ArrayCollection = new ArrayCollection();
public function Gym2(target:IEventDispatcher=null)
{
super(target);
}
public function addSet(set:GymSet):void {
sets.addItem(set);
}
}
}
GymSetRenderer.mxml
<?xml version="1.0" encoding="utf-8"?>
<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="false" xmlns:local="*">
<s:layout>
<s:VerticalLayout />
</s:layout>
<s:Label fontSize="27" text="{data.title}"/>
<s:DataGroup dataProvider="{data.data}" itemRenderer="GymButton2">
<s:layout>
<s:HorizontalLayout />
</s:layout>
</s:DataGroup>
</s:ItemRenderer>
GymButton2.mxml
<?xml version="1.0" encoding="utf-8"?>
<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">
<fx:Script>
<![CDATA[
protected function onClick(event:MouseEvent):void
{
data = data + 1;
}
]]>
</fx:Script>
<s:Button label="{data}" height="70" click="onClick(event)"/>
</s:ItemRenderer>

Related

Adding images dynamically to scroller

i am new to flex.i am trying add images dynamically in flex using file referencei need to add images in scroller.i use this below code but adding image was not visible.can anyone help me regarding this issue pls.Thanks in advance
<?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="955" minHeight="600"
xmlns:net="flash.net.*">
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.controls.Image;
import mx.utils.ObjectUtil;
private var myImage:Image;
private function OnbuttonClick(evt:MouseEvent):void {
var arr:Array = [];
arr.push(new FileFilter("Images", ".gif;*.jpeg;*.jpg;*.png"));
fileReference.browse(arr);
}
private function FileRefSelect(evt:Event):void {
fileReference.load();
}
private function FileRefComplete(evt:Event):void {
Alert.show(ObjectUtil.toString(fileReference));
myImage = new Image();
//img.source = fileReference.data;
myImage.maxWidth = 100;
myImage.maxHeight = 100;
myImage.source = fileReference.data;
vg.addChild(myImage);
}
]]>
</fx:Script>
<fx:Declarations>
<net:FileReference id="fileReference"
select="FileRefSelect(event);"
complete="FileRefComplete(event);" />
</fx:Declarations>
<mx:ControlBar>
<mx:Button id="btn" label="Browse Your Image" click="OnbuttonClick(event);" />
</mx:ControlBar>
<s:Scroller id="scrllr" x="50" y="100" width="100" height="280" focusEnabled="false"
hasFocusableChildren="true">
<s:VGroup id="vg">
</s:VGroup>
</s:Scroller>
</s:Application>
You need to use vg.addElement(myImage); instead of vg.addChild(myImage);. I am assuming you would also have got an exception mentioning the same.

Need 2 way binding between 2 components flex 4

Can anyone tell me how to do 2-way Binding between 2 components?
I have a TabGroup, in which I created 2 tabs.. Each tab has each component...
First tab: Some form is there and submit button
Second Tab: Datagrid
So, when I enter some details and click Submit button, 1 row should be added in Datagrid.. This functionality is working, BUT when i double click the row in Datagrid, the row details from Datagrid should be filled up in Form which iam not getting this..
PLease check below code , run it, and provide me solution:
Main.mxml
<?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"
xmlns:components="components.*"
creationComplete="init()">
<fx:Script>
<![CDATA[
import components.EmployeeSingleton;
[Bindable]
public var empSingleton: EmployeeSingleton;
public function init(): void
{
empSingleton = EmployeeSingleton.getInstance();
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:VGroup>
<s:TabBar dataProvider="{contact}" />
<mx:ViewStack id="contact"
resizeToContent="true">
<components:ContactInfo id="contactInfo"
label="Employee Info"
empSingleton="{empSingleton}"/>
<components:ContactList label="Employee List"
empSingleton="{empSingleton}"/>
</mx:ViewStack>
</s:VGroup>
</s:Application>
EmployeeSingleton.as
package components
{
import mx.collections.ArrayCollection;
[Bindable]
public final class EmployeeSingleton
{
private static var instance: EmployeeSingleton;
public var empData: ArrayCollection;
public function EmployeeSingleton()
{
}
public static function getInstance(): EmployeeSingleton
{
if(instance == null)
instance = new EmployeeSingleton();
return instance;
}
}
}
EmployeeVO.as
package vo
{
[Bindable]
public class EmployeeVO
{
public function EmployeeVO()
{
}
public var empName: String;
public var address: String;
public var state: String;
public var city: String;
public var zip: String;
}
}
ContactInfo.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:NavigatorContent xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" width="400" height="300">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import vo.EmployeeVO;
public var empSingleton: EmployeeSingleton;
private var empVO : EmployeeVO;
private var empCollection : ArrayCollection = new ArrayCollection();
protected function submit_clickHandler(event:MouseEvent):void
{
empVO = new EmployeeVO();
empVO.empName = empName.text;
empVO.address = address.text;
empVO.city = city.text;
empVO.state = state.text;
empVO.zip = zip.text;
empCollection.addItem(empVO);
empSingleton.empData = empCollection;
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:Form>
<s:FormItem label="Name">
<s:TextInput id="empName" />
</s:FormItem>
<s:FormItem label="Address">
<s:TextInput id="address" />
</s:FormItem>
<s:FormItem label="City">
<s:TextInput id="city" />
</s:FormItem>
<s:FormItem label="State">
<s:TextInput id="state" />
</s:FormItem>
<s:FormItem label="Zip">
<s:TextInput id="zip" />
</s:FormItem>
<s:FormItem>
<s:Button id="submit"
label="Submit"
click="submit_clickHandler(event)"/>
</s:FormItem>
</s:Form>
</s:NavigatorContent>
ContactList.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:NavigatorContent xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" width="400" height="300"
>
<fx:Script>
<![CDATA[
[Bindable]
public var empSingleton: EmployeeSingleton;
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:DataGrid id="empData"
dataProvider="{empSingleton.empData}"/>
</s:NavigatorContent>
Awaiting for solution, please run above code and provide me solution for 2-way binding
You don't need to bind for 'update for on double click on an item in list'. Bindings are very tightly coupled. What you should do instead is listen for double-click events on list and update form with a item information that was double-clicked on.

Change Background Color of datagrid cell based on more than one condition in Flex

Hi I'm very new to Adobe Flex, apologize if my question sounds stupid. Anyhow here it is.
I am trying simple datagrid which checks basically 2 conditions
1) If the Artist is 01 and Album is 'Album 01' set Background to corresponding cell in Column 'Year'.
With my below code 'set Style' to Background Color as property is not working but changing the font color is working and secondly i am not sure how to write the code to get the above nested conditions working? If anybody could help me in this aspect i would be really be grateful.
Thank you! in Advance.
Below is the code:
Newdatagrid.mxml
<?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="955" minHeight="600" >
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.controls.Alert;
[Bindable]
public static var initDG:ArrayCollection = new ArrayCollection([
{Artist:'01', Album:'Album 01', Year:'2008'},
{Artist:'01', Album:'Album 02', Year:'2009'},
{Artist:'03', Album:'Album 03', Year:'2007'},
{Artist:'03', Album:'Album 04', Year:'2003'},
]);
]]>
</fx:Script>
<s:VGroup>
<s:DataGrid id="myGrid" width="360" dataProvider="{initDG}">
<s:columns>
<s:ArrayList>
<s:GridColumn dataField="Artist" headerText="Artist" itemRenderer="CellRenderer"/>
<s:GridColumn dataField="Album" headerText="Album" itemRenderer="CellRenderer"/>
<s:GridColumn dataField="Year" headerText="Year" itemRenderer="CellRenderer"/>
</s:ArrayList>
</s:columns>
</s:DataGrid>
</s:VGroup>
</s:Application>
Renderer:
<?xml version="1.0" encoding="utf-8"?>
<s:GridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
implements="mx.controls.listClasses.IDropInListItemRenderer">
<fx:Script>
<![CDATA[
import mx.controls.dataGridClasses.DataGridListData;
import mx.controls.listClasses.BaseListData;
import mx.controls.Alert;
private var _listData:BaseListData;
[Bindable]private var isSelected:Boolean = false;
override public function set data( value:Object ) : void
{
super.data = value;
lblData.text = data[column.dataField];
if (data[column.dataField].valueOf() >= 2008){
//styleName="myStyles.BgColor";
setStyle('backgroundColor',0xFFFF00);
}else{
setStyle('backgroundColor',0x32CD32);
}
}
[Bindable]public function get listData() : BaseListData
{
return _listData;
}
public function set listData( value:BaseListData ) : void
{
_listData = value;
}
]]>
</fx:Script>
<s:Label id="lblData" top="9" left="7" width="100%" height="100%" textAlign="center"/>
</s:GridItemRenderer>
My Desired Output: Condition: If Artist=01 and Year >= 2008 then cell Background of Year change to Red
The class GridItemRenderer has no such style backgroundColor.
So it has no effect setting it.
What you can do is to add a Rect to the ItemRenderer and set its color property according to your condition.
an example would be something like:
<?xml version="1.0" encoding="utf-8"?>
<s:GridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" clipAndEnableScrolling="true">
<fx:Script>
<![CDATA[
override public function prepare(hasBeenRecycled:Boolean):void {
if(this.data) {
if(this.data.Year >= 2008 && this.data.Artist == '01' && column.dataField == 'Year')
bgColor.color = 0xFF0000;
else
bgColor.color = 0xFFFFFF;
}
}
]]>
</fx:Script>
<s:Rect top="0" bottom="0" left="0" right="0">
<s:fill>
<s:SolidColor id="bgColor" color="0xFFFFFF"/>
</s:fill>
</s:Rect>
<s:Label id="labelDisplay" top="9" left="7"/>
</s:GridItemRenderer>
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication 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="955" minHeight="600" >
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.controls.Alert;
[Bindable]
public static var initDG:ArrayCollection = new ArrayCollection([
{Artist:'01', Album:'Album 01', Year:'2008'},
{Artist:'01', Album:'Album 02', Year:'2009'},
{Artist:'03', Album:'Album 03', Year:'2007'},
{Artist:'03', Album:'Album 04', Year:'2003'},
]);
]]>
</fx:Script>
<s:VGroup>
<s:DataGrid id="myGrid" width="360" dataProvider="{initDG}">
<s:columns>
<s:ArrayList>
<s:GridColumn dataField="Artist" headerText="Artist"/>
<s:GridColumn dataField="Album" headerText="Album"/>
<s:GridColumn dataField="Year" headerText="Year" itemRenderer="CellRenderer"/>
</s:ArrayList>
</s:columns>
</s:DataGrid>
</s:VGroup>
</s:WindowedApplication>
----------------------------CellRenderer.mxml------------------------
<?xml version="1.0" encoding="utf-8"?>
<s:GridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" clipAndEnableScrolling="true">
<fx:Script>
<![CDATA[
override public function prepare(hasBeenRecycled:Boolean):void {
lblData.text = data[column.dataField]
if(this.data) {
lblData.text = data[column.dataField];
if(this.data.Year >= 2008&&this.data.Artist==01)
bgColor.color = 0xFF0000;
else
bgColor.color = 0xFFFFFF;
}
}
]]>
</fx:Script>
<s:Rect top="0" bottom="0" left="0" right="0">
<s:fill>
<s:SolidColor id="bgColor" color="0xFFFFFF"/>
</s:fill>
</s:Rect>
<s:Label id="lblData" top="9" left="7" width="100%" height="100%" textAlign="center"/>
</s:GridItemRenderer>

changing the state of the variable from the child component using custom event

this is the main application
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
verticalAlign="middle"
backgroundColor="white" layout="absolute" initialize="init();" xmlns:MyComp="screens.*" >
<mx:Script>
<![CDATA[
import screens.MyEvent;
private function init():void
{
systemManager.addEventListener("data_transfer",handleDataTransfer);
}
private function handleDataTransfer(evt:MyEvent):void{
this.myViewStack.selectedIndex=1;
}
]]>
</mx:Script>
<mx:ViewStack id="myViewStack" selectedIndex="0" width="1110" height="636">
<MyComp:Welcome />
<MyComp:Screen id="fillPage" />
</mx:ViewStack>
</mx:Application>
this is my Welcome component
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="930" height="300" >
<mx:Script>
<![CDATA[
private function changeHandler():void{
var myEVT:MyEvent = new MyEvent("data_transfer",false, true);
this.dispatchEvent(myEVT);
}
]]>
</mx:Script>
<mx:Button label="Fill The Form" id="fillForm" click="changeHandler()"/>
</mx:Canvas>
this is my screen.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300">
<mx:Label text="hai">
</mx:Label>
</mx:Canvas>
this is MYEvent.as
package screens
{
import flash.events.Event;
public class MyEvent extends Event
{
public static const DATA_TRANSFER:String = "data_transfer";
public function MyEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
}
}
}
I want to get the Screen mxml by clicking the button at welcome mxml...i am initial learner..
but it is not working..Please help me..
As your custom event has bubbling=false, it wont bubble upto the systemManager. try:
var myEVT:MyEvent = new MyEvent("data_transfer", true, true);
Alternatively, add the listener to the object that is dispatching the event:
welcomePage.addEventListener("data_transfer",handleDataTransfer);
....
<MyComp:Welcome id="welcomePage" />
Second solution is generally better/preferred - less event bubbling is a good thing

Flex 4: State Change Event

Is there any event in Flex 4 that I can use to detect a state change?
I know this question is old but by googling for state change events I still get here so for people that want to know:
There is a StateChangeEvent.CURRENT_STATE_CHANGE event that is dispatched by the component, so your application can also listen for that.
In your listener function you can then acces the StateChangeEvent.oldState and StateChangeEvent.newState properties.
If you are talking about view states the answer is yes, you can listen for the enterState event like this (sorry for the simplicity of the example, it's part of a project I'm working on and I removed any relevant parts of the 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="800" minHeight="600"
currentState="loading">
<fx:Script>
<![CDATA[
import mx.controls.Alert;
private function onEnterLoadingState():void{
Alert.show("Enter the loading state.", "Application");
}
private function onEnterLoginState():void{
Alert.show("Enter the login state.", "Application");
}
private function onEnterAddState():void{
Alert.show("Enter the addUser state.", "Application");
}
private function changeState(state:String):void{
currentState = state;
}
]]>
</fx:Script>
<s:states>
<s:State name="loading" enterState="onEnterLoadingState()"/>
<s:State name="login" enterState="onEnterLoginState()"/>
<s:State name="addUser" enterState="onEnterAddState()"/>
</s:states>
<s:Panel id="loadView" includeIn="loading" title="Loading">
<s:Button label="Go to login" click="changeState('login')"/>
</s:Panel>
<s:Panel id="loginView" includeIn="login" title="Login">
<s:Button label="Go to addUser" click="changeState('addUser')"/>
</s:Panel>
<s:Panel id="addView" includeIn="addUser" title="AddUser">
<s:Button label="Return to loading" click="changeState('loading')"/>
</s:Panel>
</s:Application>
And there is an exitState event in case you need it. I hope this helps you.
There are multiple state events you can listen for on any UIComponent class:
FlexEvent.STATE_CHANGE_COMPLETE
FlexEvent.STATE_CHANGE_INTERRUPTED
StateChangeEvent.CURRENT_STATE_CHANGING
StateChangeEvent.CURRENT_STATE_CHANGE
FlexEvent.ENTER_STATE
FlexEvent.EXIT_STATE
MXML:
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
enterState="windowedapplication1_enterStateHandler(event)"
exitState="windowedapplication1_exitStateHandler(event)"
currentStateChange="windowedapplication1_currentStateChangeHandler(event)"
currentStateChanging="windowedapplication1_currentStateChangingHandler(event)"
stateChangeInterrupted="windowedapplication1_stateChangeInterruptedHandler(event)"
stateChangeComplete="windowedapplication1_stateChangeCompleteHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
protected function windowedapplication1_stateChangeCompleteHandler(event:FlexEvent):void
{
}
protected function windowedapplication1_stateChangeInterruptedHandler(event:FlexEvent):void
{
}
protected function windowedapplication1_currentStateChangeHandler(event:StateChangeEvent):void
{
var oldState:String = event.oldState;
var newState:String = event.newState;
}
protected function windowedapplication1_currentStateChangingHandler(event:StateChangeEvent):void
{
var oldState:String = event.oldState;
var newState:String = event.newState;
}
protected function windowedapplication1_enterStateHandler(event:FlexEvent):void
{
}
protected function windowedapplication1_exitStateHandler(event:FlexEvent):void
{
}
]]>
</fx:Script>
</s:WindowedApplication>