Need 2 way binding between 2 components flex 4 - actionscript-3

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.

Related

Flex ItemRender Not Updating Data Source

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>

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.

Simple flex popup with dispatch event in child and listener in parent not working

Parent.mxml
This file is calling the popup class below when the button is clicked.
<?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.controls.Alert;
import mx.managers.PopUpManager;
var popup:pop = null ;
protected function clickHandler(event:MouseEvent):void
{
popup = PopUpManager.createPopUp(this,pop,true) as pop;
popup.ok.addEventListener(MouseEvent.CLICK, captureComments);
popup.close();
}
var str:String="";
private function captureComments():void{
Alert.show("Invoked Event Listener", "Alert");
str=popup.comments;
}
]]>
</fx:Script>
<mx:Button id="id1" label="Click" click="clickHandler(event)"/>
<s:Label id="lbl" height="18" width="282" text={str} />
</s:Application>
Child.mxml
This file is the popup reference, creating popup.
I have configured the close action and cancel buttons to work as needed, but unable to propagate the text entered in comment are back to the parent.
<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
layout="vertical" width="524" height="322"
showCloseButton="true"
close="close()" chromeColor="#CCCCCC"
horizontalAlign="center" verticalAlign="middle" color="#000000">
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.managers.PopUpManager;
import mx.rpc.events.ResultEvent;
[Bindable]public var comments:String;
public function close(): void{
PopUpManager.removePopUp(this);
}
private function save(): void{
if(comments == null){
comments = "";
}
dispatchEvent(new ResultEvent(comments));
}
]]>
</fx:Script>
<mx:HBox width="100%" height="70%">
<mx:VBox width="100%" height="100%">
<mx:TextArea id="comment" text="{comments}" width="100%" height="80%" change="comments = event.target.text">
</mx:TextArea>
<mx:HBox horizontalAlign="center" width="100%" height="20%">
<s:Button id="ok" label="OK" chromeColor="#CCCCCC" click="save()" fontWeight="bold"/>
<s:Button id="cancel" label="Cancel" chromeColor="#CCCCCC" click="close()" fontWeight="bold"/>
</mx:HBox>
</mx:VBox>
</mx:HBox>
</mx:TitleWindow>
You are dispatching a ResultEvent, like this:
dispatchEvent(new ResultEvent(comments));
However, the event type is the user entered input. Check out the ResultEvent constructor. The first argument is the event type. I have no idea how you'll be able to consistently listen for an event type that is unknown at compile time.
I think you are trying to pass your custom data back to your parent class. My preference would be to use a custom event for this; but if you wanted to use a ResultEvent you could pass your comments in the result property:
dispatchEvent(new ResultEvent(ResultEvent.RESULT,false,true,comments));
In your parent file, add an event listener like this:
popup.addEventListener(ResultEvent.RESULT, processResult);
You should be able to get at your comments value as a property on the event:
protected function processResult(event:ResultEvent):void{
str=event.result
}
Another thing I've done as well is in the Child Container Create a public variable to pass the function from the parent ie:
in parent:
protected function captureComments(comments:String):void{
str=comments;
}
in child :
declare a public var and add the function to the save() function
public var parentFunction:Function;
private function save(): void{
if(comments == null){
comments = "";
}
parentFunction(comments);
Then when Creating your popup container in the parent:
protected function clickHandler(event:MouseEvent):void
{
popup = PopUpManager.createPopUp(this,pop,true) as pop;
popup.parentFunction = captureComments;
popup.close();
}

Dynamically added FormItem doesn't show error text

I am dynamically creating a form on runtime of my application. The content of my form item (lets call it MyFormItemContent) looks like this (simplified):
<?xml version="1.0" encoding="utf-8"?>
<s:BorderContainer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
width="100%" borderAlpha="0.0">
<fx:Declarations>
<utils:DataItemValidator dataItem="{referenceToDataItem}"
source="{this}"/>
</fx:Declarations>
<s:HGroup width="100%">
<s:TextInput width="100%" text="#{bindingToText}"/>
<s:CheckBox width="14" selected="{refToBoolean}"/>
</s:HGroup>
</s:BorderContainer>
and the the code for the the validator we are using. It works fine other parts of the application and debuging shows that a message exists but is not shown.
/**
* This class effectively does *not* validate the given 'value', but just returns
* his 'dataItem's attached messages.
*/
public class DataItemValidator extends Validator {
private var _dataItem:StatefulDataItem;
public function get dataItem():StatefulDataItem {
return _dataItem;
}
public function set dataItem(dataItem:StatefulDataItem):void {
_dataItem = dataItem;
ChangeWatcher.watch(_dataItem, "messages", function():void {
validate();
}, false);
validate();
}
override protected function doValidation(value:Object):Array {
if (!isInitialized()) return [];
// Clear results Array.
var results:Array = [];
// If dataItem has error indicator append all messages to result array.
if (dataItem && dataItem.messages) {
for each (var message:ResultMessage in dataItem.messages) {
results.push(new ValidationResult(message.isErroneous(), null, "", message.text));
}
}
return results;
}
public function isErroneous():Boolean {
if (!dataItem) return false;
return dataItem.isErroneous();
}
private function isInitialized():Boolean {
return (dataItem != null);
}
}
The code that declares the form looks like this:
<s:Form id="myForm" width="100%" height="100%">
<s:layout>
<s:FormLayout gap="-7" paddingBottom="2" paddingLeft="2" paddingRight="2"
paddingTop="2"/>
</s:layout>
</s:Form>
And finally, the item is added to the form like this:
var formItem:FormItem = new FormItem();
formItem.label = "some text";
formItem.addElement(new MyFormItemContent());
myForm.addElement(formItem);
If the validation of MyValidator has errors a red frame apears around the BorderContainer as intended. But unfortunatly the error text that should apear right to the form item doesn't. I'm thinkin it's a layout problem because I define the validator inside the form item content before adding it to the form. I've already debugged this and read documentations a lot.
I thought it would help to know how a FormItem is added to a Form if you declare it in mxml but I couldn't find information on that either.
<?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="application2_creationCompleteHandler(event)" xmlns:local="*">
<fx:Script>
<![CDATA[
import mx.charts.series.ColumnSeries;
import mx.collections.ArrayCollection;
import mx.containers.FormItem;
import mx.events.FlexEvent;
protected function application2_creationCompleteHandler(event:FlexEvent):void
{
// TODO Auto-generated method stub
for(var i:int = 0; i < 4; i++)
{
var formItem:FormItem = new FormItem();
formItem.label = "some text";
formItem.addElement(new MyFormItemContent());
myForm.addElement(formItem);
}
}
]]>
</fx:Script>
<s:Form id="myForm" width="100%" height="100%">
<s:layout>
<s:FormLayout gap="-7" paddingBottom="2" paddingLeft="2" paddingRight="2"
paddingTop="2"/>
</s:layout>
</s:Form>
</s:Application>
form item mxml file
<?xml version="1.0" encoding="utf-8"?>
<s:BorderContainer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
width="100%" borderAlpha="0.0" xmlns:mx="library://ns.adobe.com/flex/mx" creationComplete="bordercontainer1_creationCompleteHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import mx.events.ValidationResultEvent;
[Bindable]
private var bindingToText:String;
[Bindable]
private var refToBoolean:Boolean;
protected function bordercontainer1_creationCompleteHandler(event:FlexEvent):void
{
// TODO Auto-generated method stub
}
protected function txt_focusOutHandler(event:FocusEvent):void
{
var obj:ValidationResultEvent = validator.validate(txt.text);
error.visible = !(obj.type == "valid");
}
]]>
</fx:Script>
<fx:Declarations>
<mx:PhoneNumberValidator id="validator"/>
</fx:Declarations>
<s:HGroup width="100%">
<s:TextInput id="txt" width="100%" text="#{bindingToText}" focusOut="txt_focusOutHandler(event)"/>
<s:CheckBox width="14" selected="{refToBoolean}"/>
<s:Label id="error" visible="false" backgroundColor="red" text="This Field Required"/>
</s:HGroup>
</s:BorderContainer>
I am posting this code for your interest.

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>