How to Send Info From a Flex 3 Component? - apache-flex

I need some help with sending info from a component. I'm not sure how to proceed.
I'm using Alex Uhlmann's flip card class (Distortion Effects). I've got a card that has 3 faces. When the user clicks the button, it fires a change event, and in the main application, the change event calls a function, flipTo, that flips the card. The component is below:
<?xml version="1.0" encoding="utf-8"?>
<mx:Panel
xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
width="500"
height="400">
<mx:Metadata>
[Event("change", type="mx.events.Event")]
</mx:Metadata>
<mx:Script>
<![CDATA[
[Bindable]
public var backCaption:String;
]]>
</mx:Script>
<mx:Text id="myAnswer" htmlText="{backCaption}" width="100%" />
<mx:ControlBar height="40" width="100%" >
<mx:Button
x="20" y="400"
label="Flip"
click="dispatchEvent( new Event( Event.CHANGE ) );" />
</mx:ControlBar>
</mx:Panel>
The main application looks like:
<mx:Canvas id="homeStack" >
<mx:ViewStack id="flipViewStack2" x="200" y="150" >
<sides:FlipFace
id="frontFace2"
title="Newport"
change="flipTo(frontFace2, backFace2, DistortionConstants.LEFT, DistortionConstants.RIGHT);" />
<sides:FlipReverse
id="backFace2"
title="Newport: Answer"
change="flipTo(backFace2, anotherFace2, DistortionConstants.LEFT, DistortionConstants.LEFT);" />
<sides:FlipAnotherSide
id="anotherFace2"
title="Other Stuff"
change="flipTo(anotherFace2, frontFace2, DistortionConstants.RIGHT, DistortionConstants.LEFT);"/>
</mx:ViewStack>
</mx:Canvas>
<mx:Canvas id="OtherStack" >
(more code)
</mx:Canvas>
The flipTo function in the main application takes 4 parameters: the starting side, the ending side, and then two parameters that determine the direction of the flip.
Everything works great. If I hit the button, I can flip through all of the sides. But, I'd like to add a comboBox, so that the user can flip directly to the side that they want instead of having to cycle through all of the sides. (This is important as I plan to add more sides).
In the main application, please note that the sides have the number 2 in their ids. For example, frontFace2. I've got multiple sets of cards each with a different number, frontFace3, frontFace4, etc. The number determines which data is pulled from the database. (I've simplified the code for brevity).
How can I add a comboBox in the component that causes the card to flip to the selected side?
Do I need a custom event? (Unfortunately, I don't know anything about custom events). Is there a way to have the comboBox set a public variable and then somehow access that variable in the main application and call flipTo with the comboBox's chosen side? Other possibilities?
Any suggestions?
Thank you.
-Laxmidi

oh, yeah, you will need a custom event.
the custom event is your inheritance to the Event class which on it you can load more data, params, views and more.
in your case, things are a bit more simple but you will need to see what "face" the user selected and flip to it.
steps
1. create a custom event (inherit from event)
2. add a var to the event class that's called face
3. when the user selects the value from the combo, fill the face var with value and dispatch the event
4. listen to the event in the application level and then flipTo the relevant face.

Related

Component shows in Design view but not when the application is launched

This is what's happening:
I have a Tabnavigator with the following tab:
<s:NavigatorContent width="100%" height="100%" label="Add a logo" includeIn="loggedin">
<components:LogoSearch />
</s:NavigatorContent>
When I change the state to "loggedin" with following code:
protected function Login_getStateHandler(event:Event):void
{
this.currentState = "loggedin";
}
the navigatorContent shows but not the component "LogoSearch", in design view however it does show when I switch states.
There are no states defined in "LogoSearch" and should show...?
When I include the tabnavigator in "normal" aswell as "loggedin", then change the state to "loggedin", the component "LogoSearch" shows. When I only show the tabnavigator in "loggedin", change the state to "loggedin", the component "LogoSearch" doesn't show.
Any idea why this is happening? I'm no pro in flex at all so feel free to point me on my mistake. Thanks.
Tried working with invalidateDisplayList() and invalidateProperties() as suggested by Tianzhen Lin. Still nothing showing.
<s:NavigatorContent width="100%" height="100%" label="Add a logo" includeIn="loggedin" id="AddLogoTab" >
<s:Label text="test" id="test" />
</s:NavigatorContent>
And :
protected function Login_getStateRegisterHandler(event:Event):void
{
this.currentState = "register";
test.invalidateDisplayList();
test.invalidateProperties();
test.validateNow();
AddLogoTab.invalidateDisplayList();
AddLogoTab.invalidateProperties();
AddLogoTab.validateNow();
}
Whatever I do, the content of the NavigatorContent won't show after statechange.
To narrow down the problems you have, you may start by eliminating includeIn="loggedin" in your code, this would at least ensure that your component is showing properly.
Next, I would put a breakpoint at your Login_getStateHandler function, and see if it is ever called. If not, then it is somewhere in your wiring that the handler is not called. You may post more code here to get help.

Spark List with Buttons

I have a Spark List with a data provider consisting of a list of filled out form applications. What is the best way to add a button to each List Item (form application)? This button will be named Open and will navigate to the specified form application.
Thanks in advance for any advice!
This is similar to what #www.Flextras.com said, so I'm not going to repeat that. However, I'll add an example and one or two things.
Your custom ItemRenderer might look like this:
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Script>
<![CDATA[
import mx.events.ItemClickEvent;
private function requestForm():void {
var event:ItemClickEvent = new ItemClickEvent(ItemClickEvent.ITEM_CLICK);
event.index = itemIndex;
event.item = data;
owner.dispatchEvent(event);
}
]]>
</fx:Script>
<s:Label id="labelDisplay" verticalCenter="0" />
<s:Button right="0" label="open" verticalCenter="0" click="requestForm()" />
</s:ItemRenderer>
Two things that differ from Flextras' answer:
I use the built-in ItemClickEvent instead of a custom event > less
coding
I dispatch the event on the owner of the ItemRenderer, which
is in fact the List that contains this ItemRenderer. Because of this,
you don't need to bubble the Event.
Now to open the form when the Button is clicked, do something like this:
myList.addEventListener(ItemClickEvent.ITEM_CLICK, openForm);
private function openForm(event:ItemClickEvent):void {
trace("open " + event.item.toString());
}
Use a custom itemRenderer which displays the button along w/ your itemRenderer data (form application).
When the button is clicked; dispatch a custom event which bubbles. You may have to include some identifier for the form application this button click represents.
Listen to the event on the list class using the addEventListener() method. You can't use MXML since you'll be using a custom event undefined in the List's default metadata.
In your listener, perform the relevant UI changes to display your form application.

How to check the state of a Radio Button in Flex 3?

I'm working on a template for dynamic questionnaires in Flex. More detailed description in my previous thread HERE
To create the questionnaire, I use nested repeaters - one for the questions and one for the answers (as their amount may vary).
<mx:Repeater id="r" dataProvider="{questions}">
<mx:Label text="{r.currentItem.question}" width="200"/>
<mx:Repeater id="r2" dataProvider="{r.currentItem.answers}">
<mx:RadioButton label="{r2.currentItem.text}" width="200"
click="answerHandler(event, event.currentTarget.getRepeaterItem())"/>
</mx:Repeater>
</mx:Repeater>
To understand my data providers, it's probably best to check the answer for my previous thread - easier than if I try to explain it here.
The question here is... As you can see, I created click event handler for each radio button and my plan was to do playerScore++ every time the user chose correctly (which can be achieved by checking the Boolean property "correct" of sent RepeaterItem).
However, I see now that even if the button is selected already, I can still click on it more times, and even though it's not changing anything in the view, it increments the score every time.. I would also have to handle situation in which the user changes his mind (I could give + points for each good answer and - points for wrong, but this would mean, that if the user chose more wrong answers, my score will be negative and I don't want it).
So it would be way way easier to just have a Submit button and check the states of all my buttons and if they are correct only after the user clicks "submit". Is it possible?
I recommend you to refer to the following sample and add RadioButtonGroup to your repeater groups and listen to change events instead of click. You can listen change event right in RadioButtonGroup and check if (radioGroup.selectedValue.correct) for correctness of new selection. See corresponding documentation.
To have possibility to assign radiogroups unique name you have to extract inner repeater with answers into separate component. Breaking your application into smaller components can make your application more clear and readable. You can treat every MXML file as a class (as in OOP) but in declarative form. And to tell the true every MXML component is a class which inherited from root-node-class.
Lets look at the code.
First, our inner component which serves answers:
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Metadata>
[Event(name="rightAnswerEvent", type="AnswerEvent")]
</mx:Metadata>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
public var answers:ArrayCollection;
protected function answerGroup_changeHandler(event:Event):void
{
if (answerGroup.selectedValue.correct)
dispatchEvent(new AnswerEvent(AnswerEvent.RIGHT_ANSWER_EVENT));
}
]]>
</mx:Script>
<mx:RadioButtonGroup change="answerGroup_changeHandler(event)" id="answerGroup" />
<mx:Repeater dataProvider="{answers}" id="answersRepeater">
<mx:RadioButton group="{answerGroup}" label="{answersRepeater.currentItem.text}"
value="{answersRepeater.currentItem}" />
</mx:Repeater>
</mx:VBox>
It gets answers collection as input and fires our custom event to inform some components about right answer (see Metadata tag).
Our custom event is pretty simple an looks like the following:
package
{
import flash.events.Event;
public class AnswerEvent extends Event
{
public static const RIGHT_ANSWER_EVENT:String = "rightAnswerEvent";
public function AnswerEvent(type:String)
{
super(type);
}
}
}
So now our top level component:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application layout="vertical" xmlns:local="*"
xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var questions:ArrayCollection = new ArrayCollection();
[Bindable]
private var scoreCounter:int;
]]>
</mx:Script>
<mx:Label text="{'Score ' + scoreCounter}" />
<mx:Repeater dataProvider="{questions}" id="questionRepeater">
<mx:Label text="{questionRepeater.currentItem.question}" />
<local:AnswerGroup answers="{questionRepeater.currentItem.answers}" rightAnswerEvent="scoreCounter++" />
</mx:Repeater>
</mx:Application>
I omitted initialization code to populate our Question and Answer domain objects with data from XML (see previous thread).
So now we have compact modularized code where every part solves its own task.
Hope this helps!

More than one titleWindow in a Flex Application

I'm a GIS Analyst that was moved to an Analyst Programmer position. This has been a hard transition for me as I don't have much of a programming background, but I was thrown into it.
I'm working on a Flex app inside a jsp page. Essentially it is a grid 3x2 that has images and text. What I am trying to do is have more than one titleWindow reference in this page, so that when an image is clicked a titleWindow is opened. (If anyone has a better idea, especially if it has to do with a hover I am very open to that!) Currently I have it working for one image. However, when I try to add a second function it errors on me. "Error 1021: Duplicate function definition" Below is the entire code for the main page that calls up the titleWindow. The code below is what gives the Error 1021.
<?xml version="1.0" encoding="utf-8"?>
<![CDATA[
import flash.geom.Point;
import mx.containers.TitleWindow;
import mx.core.IFlexDisplayObject;
import mx.managers.PopUpManager;
import windows.SimplePopupWindow;
private var point1:Point = new Point();
private function showWindow():void {
var login:SimpleTitleWindowExample=SimpleTitleWindowExample(PopUpManager.createPopUp( this, SimpleTitleWindowExample , true));
point1.x=131;
point1.y=119;
point1=roadStatus.localToGlobal(point1);
}
private var point2:Point = new Point();
private function showWindow():void {
var login:SimpleTitleWindowExampleFlood=SimpleTitleWindowExampleFlood(PopUpManager.createPopUp( this, SimpleTitleWindowExampleFlood , true));
point2.x=289;
point2.y=119;
point2=floodplain.localToGlobal(point2);
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:BorderContainer x="10" y="0" width="750" height="600" backgroundColor="#BBB082" backgroundAlpha="1.0" cornerRadius="20" borderColor="#E8DBA7">
<s:Panel x="10" y="10" width="728" height="578" cornerRadius="20" chromeColor="#983D3A" borderColor="#F1EFE7" backgroundColor="#BBB082">
<mx:Image x="131" y="119" width="150" height="115" source="file://GIS Map Portal/images/Map Images/SJCRoadStatus2_small.jpg" id="roadStatus" click="showWindow();"/>
<mx:Image x="289" y="119" width="150" height="115" source="file://GIS Map Portal/images/Map Images/SJCRoadStatus_small.jpg" id="floodplain" click="showWindow();"/>
<mx:Image x="447" y="119" width="150" height="115" source="file://GIS Map Portal/images/Map Images/SJCRoadStatus2_small.jpg"/>
<s:Label x="131" y="242" text="SJC Road Status"/>
<s:Label x="289" y="242" text="SJC Floodplain"/>
<s:Label x="447" y="242" text="Assessor's Parcels"/>
<mx:Image x="131" y="262" width="150" height="115" source="file://GIS Map Portal/images/Map Images/SJCRoadStatus_small.jpg"/>
<mx:Image x="289" y="262" width="149" height="115" source="file://GIS Map Portal/images/Map Images/SJCRoadStatus2_small.jpg"/>
<mx:Image x="446" y="262" width="151" height="115" source="file://GIS Map Portal/images/Map Images/SJCRoadStatus_small.jpg"/>
<s:Label x="131" y="385" text="Label"/>
<s:Label x="289" y="385" text="Label"/>
<s:Label x="446" y="385" text="Label"/>
<s:Label x="229" y="24" text="San Juan County Web Maps" fontFamily="Calvin and Hobbes" fontSize="25"/>
</s:Panel>
</s:BorderContainer>
Below is the titleWindow code. This code works so far!
<?xml version="1.0" encoding="utf-8"?>
<mx:Script>
<![CDATA[
import mx.managers.PopUpManager;
import mx.controls.Text;
// A reference to the TextInput control in which to put the result.
public var loginName:Text;
// Event handler for the OK button.
private function returnName():void {
//loginName.text="Name entered: " + userName.text;
PopUpManager.removePopUp(this);
}
]]>
</mx:Script>
<mx:HBox width="323" height="147" borderColor="#E8DBA7" dropShadowVisible="true">
<mx:Text text="The San Juan County GIS Department maintains aninteractive web map dedicated for researching county roads, but also includes city limits, lakes and rivers, and other geographic data.
" width="319" height="76" textAlign="center" color="#FFFFFF"/>
</mx:HBox>
<mx:HBox>
<mx:Button label="Go" click="navigateToURL(new URLRequest(''), 'quote')"/>
<mx:Button label="Back" click="PopUpManager.removePopUp(this);"/>
</mx:HBox>
Question: What code do I need to change above to be able to add more than one titleWindow (up to 6), or what code can I use for a hover to open a "window" or tool tip?
If anyone has any ideas or can direct me at all that would be great. I appreciate it!
Sounds like you just got thrown in the deep end. Generally speaking theres no limitation on the number of title windows you can have open, the PopUpManager class handles any UIComponent you tell it to open as a pop up and one of the arguments for the .createPopUp or addPopUp static methods on the manager will take a modal parameter which specifies if the user interaction should be blocked (indicated by blurring the application) or if the window should just be shown. It seems rather this error is stemming from your extension of the TitleWindow (the SimpleTitleWindowExample) can you post that code. Also as starting points on the topic check out the following documentation:
General Flex:
http://www.adobe.com/devnet/flex/videotraining.html
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/index.html
^ notice the runtimes and products selection options at the top of the screen, select according to SDK you're building with (or select SDK based on features)
PopUpManager:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/managers/PopUpManager.html#createPopUp()
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/managers/PopUpManager.html#addPopUp()
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/managers/PopUpManager.html#removePopUp()
Tooltips:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/managers/ToolTipManager.html#createToolTip()
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/managers/ToolTipManager.html#destroyToolTip()
If you're still having troubles definitely post the code for the custom TitleWindow, also what version of the SDK you're using so I can try to replicate.
EDIT:
Ah okay seeing the rest of your code clears it up... you can't have two functions that have the same exact name so in your code you have showWindow as a function that is declared two times (I'm not sure how this is getting past compilation, I would have imagined the compiler would be smart enough to see this error before run-time, but it is what it is). Change the other showWindow to be something like showOtherWindow or something along those lines. It also looks like you come from a procedural programming background (C or some other non-OOP language) Object Oriented programming takes a little while to get your head around but makes a whole lot more sense when it comes to solving real world problems once you understand it, basically you're setting up descriptions and sending messages between objects using method calls and when you define a class, via AS or MXML you're defining the methods (order of method/property definitions doesn't functionally matter, things are still procedural, like step by step within the methods but the order of method declaration or property declaration has no effect).
This may be helpful:
http://www.codeproject.com/KB/architecture/OOP_Concepts_and_manymore.aspx
I'm basically at the opposite end of the spectrum in terms of skills, I have a formal education from DePaul University in computer science but at my current position am doing a lot of google maps flash code so I'm finding myself more and more needing to understand Datums and other GIS specialty info (just thought it was sort of interesting to find someone at the same intersection but going the other way :).

popup editor for datagrid items - hangs the browser

i've got a pretty straightforward thing: a datagrid which renders some items. clicking on an item would bring up a popup editor (as the item has lots of properties and may not be edited right in the datagrid).
the popup contains just a form and a [Bindable] reference to the item it edits (which is passed from itemClick handler of the datagrid). form's default values are taken by binding to corresponding item properties with {} notion, while form values are bound back to the item using mx:Binding tags.
and now the problem. when the popup is brought up for the first time, everything is fine. however, when after being closed the popup is brought up again by clicking on the same item, the browser hangs (afaik because of change watchers being endlessly fired resulting in stackoverflow or something similar).
we have same behaviour in Safari, IE and Chrome, so i guess it's not to do with something browser-related. removing either [Bindable] from the item reference in the popup or mx:Binding tags from editors suppresses the problem, but of course the editing no longer works.
i'm banging my head against the wall for several days already, but still can't make it work. does it ring a bell to someone, what can be wrong in here (what can be damn easier that this)?
here's the code of the popup:
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" title="Details"
showCloseButton="true" close="PopUpManager.removePopUp(this);" creationComplete="PopUpManager.centerPopUp(this)">
<mx:Script>
<![CDATA[
import mx.managers.PopUpManager;
import my.Detail;
[Bindable] private var _documentDetail:Detail;
public function set documentDetail(value:Detail):void {
this._documentDetail = value;
}
public function set readOnly(value:Boolean):void {
if (value) {
this.currentState = "read-only";
}
}
]]>
</mx:Script>
<mx:states>
<mx:State name="read-only">
<mx:SetProperty target="{startDate}" name="enabled" value="false"/>
<mx:SetProperty target="{comments}" name="enabled" value="false"/>
</mx:State>
</mx:states>
<!--
<mx:Binding source="this.startDate.selectedDate" destination="_documentDetail.startDate"/>
<mx:Binding source="this.comments.text" destination="_documentDetail.comment"/>
-->
<mx:VBox width="100%" height="100%">
<mx:FormItem label="{resourceManager.getString('eRequestAppli','startdate')}:" labelWidth="160" width="100%">
<mx:DateField id="startDate" width="100%" selectedDate="{_documentDetail.startDate}" formatString="{resourceManager.getString('eRequestAppli', 'dateformat')}" editable="false"/>
</mx:FormItem>
<mx:FormItem label="{resourceManager.getString('eRequestAppli','comments')}:" labelWidth="160" width="100%" height="79">
<mx:TextArea id="comments" width="100%" height="100%" text="{_documentDetail.comment}" editable="false"/>
</mx:FormItem>
</mx:VBox>
</mx:TitleWindow>
here's how i call it:
private function show(detail:Detail, readOnly:Boolean=false):void {
var popup:fxc_ProposalDetail =
fxc_ProposalDetail(PopUpManager.createPopUp(UIComponent(Application.application), fxc_ProposalDetail, true));
popup.documentDetail = detail;
popup.readOnly = readOnly;
}
Thanks for posting the code. Now I might be able to help.
Where are you handling the close event of the popup? Besure to use something like this:
private function handleCloseEvent():void {
PopUpManager.removePopUp(this);
}
Besides that it appears your problem has to do with the following:
Because a module is loaded into a child domain, it owns class definitions that are not in the main application’s domain. For example, the first module to load the PopUpManager class becomes the owner of the PopUpManager class for the entire application because it registers the manager with the SingletonManager. If another module later tries to use the PopUpManager, Adobe ® Flash® Player throws an exception.
The solution is to ensure that managers such as PopUpManager and any other shared services are defined by the main application (or loaded late into the shell’s application domain). When you promote one of those classes to the shell, the class can then be used by all modules. Typically, this is done by adding the following to a script block:
import mx.managers.PopUpManager;
private var popUpManager:PopUpManager;
The module that first uses the component owns that component’s class definition in its domain. As a result, if another module tries to use a component that has already been used by another module, its definition will not match the existing definition. To avoid a mismatch of component definitions, create an instance of the component in the main application. The result is that the definition of the component is owned by the main application and can be used by modules in any child domain.
see: http://help.adobe.com/en_US/flex/using/WS2db454920e96a9e51e63e3d11c0bf69084-799a.html
for a better understanding of modules.
as suggested before, reusing the popup instead of creating a new one each time seems to have solved the issue.

Resources