Flex PopUpAnchor created manually not showing up - apache-flex

I need to create a component using ActionScript. Can't use mxml in this case.
In my component I need to create PopUpAnchor using new operator and addElement to the stage. Unfortunatelly when I'm doing it, the PopUpAnchor's displayPopUp property does not respond to any values.
Here is my the example:
<?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"
initialize="init(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import spark.components.Label;
import spark.components.PopUpAnchor;
protected function init(event:FlexEvent):void
{
var anchor:PopUpAnchor = new PopUpAnchor();
var label:Label = new Label();
label.text = 'ABC';
anchor.addChild(label);
addElement(anchor);
anchor.displayPopUp = true;
}
]]>
</fx:Script>
</s:WindowedApplication>
I'm using Flex SDK 4.5 with AIR SDK 2.6.
What am I doing wrong?

I figured it out. The problem is that i connot use addChild on anchor. I should use popUp property instead.
So, this line is WRONG:
anchor.addChild(label);
and should be corrected to this form:
anchor.popUp = label;

Related

How do you set ByteArray to IconItemRenderer in Flex 4?

I am having problems setting a ByteArray image to the "iconField" in IconItemRenderer. I think I'm halfway there as to use the "iconFunction", however what should I call to set the image in "iconField"?
Please help! Thank you in advance.
<s:IconItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
iconFunction="initializeIcon"
iconWidth="45"
iconHeight="45">
<fx:Script>
<![CDATA[
import mx.utils.Base64Decoder;
private function initializeIcon(data:Object):void
{
var imageName:String = data.image; //image is Base64 encoded data from a dynamic array
var byteArr:ByteArray;
var base64Dec:Base64Decoder = new Base64Decoder();
base64Dec.decode(imageName);
byteArr = base64Dec.toByteArray();
//set iconField? what should I do from here on.
}
]]>
</fx:Script>
</s:IconItemRenderer>
This code will solve your problem.
<?xml version="1.0"?>
<s:IconItemRenderer xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:component="spark.components.*"
iconField='byteArray'>
<fx:Script>
<![CDATA[
import mx.utils.Base64Decoder;
override public function set data(value:Object):void {
super.data = value;
var imageName:String = data.image;
var base64Dec:Base64Decoder = new Base64Decoder();
base64Dec.decode(imageName);
data.byteArray = base64Dec.toByteArray();
}
]]>
</fx:Script>
</s:IconItemRenderer>
Just fyi I think it's not best practice to put decoder into item renderer. I would recommend keep it level above.
Also keep in mind that IconItemRenderer is only available for mobile applications.

Flex 4.6 - Enable onClick (click) on an s:List or s:ArrayCollection

I have been searching thru the posts but I have not been able to find (I could have missed it) how to allow items in an s:List or s:Arraycollection to be clicked to advance to another view in an mobile app. Any help would be much appreciated!
Thanks!
<?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="onCreationComplete()"
>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.controls.Alert;
private var _listDataProvider:ArrayCollection = new ArrayCollection(['one', 'two', 'three']);
private function onCreationComplete():void
{
list.dataProvider = _listDataProvider;
list.addEventListener(MouseEvent.CLICK, onListItemClick);
}
private function onListItemClick(event:Event):void
{
Alert.show('Replace this Alert with code to go to view ' + event.currentTarget.selectedItem.toString() + '.', 'Item #' + (event.currentTarget.selectedIndex + 1).toString());
}
]]>
</fx:Script>
<s:List id="list"
horizontalCenter="0"
verticalCenter="0"
/>
</s:Application>
I'm getting the same issue. For some reasons, flash builder is importing the Alert class correctly (import mx.controls.Alert) with its full package name but the project does not compile because it says "Import alert could not be found". I am developing a mobile application using SDK 4.6 which i know doesn't have support for mx controls. This only explains why mx namespace control classes aren't importing properly. I hope this answers your question correctly as i'd advice you to find other means of alerting information to the user. Maybe write a custom alert component or use the platform's alert control via Native extensions.

Handling mouse click in Flex 4 List to find the selected item (since itemClick is gone)

I have prepared a simplified test case for my question. It will run instantly in your Flash Builder if you put the 2 files below into a project.
I'm trying to display a List of strings and a confirmation checkbox in a popup:
In the real application I dispatch a custom event with the string selected in the list, but in the test code below I just call trace(str);
My problem: if I use click event, then the window closes, even if I click at a scrollbar (the !str check below doesn't help, when an item had been selected in previous use). And if I use change event, then the window doesn't close, when I click on the same item as the last time. And the itemClick event seems not to be present in spark.components.List anymore.
Any suggestions please on how to handle this probably frequent problem?
Writing a custom item renderer and having a click event handler for each item seems to be overkill for this case, because I have strings in the list.
Test.mxml: (please click myBtn few times - to see my problems with click and change)
<?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="400" minHeight="300">
<fx:Script>
<![CDATA[
import mx.managers.PopUpManager;
private var _popup:Popup = new Popup();
private function showPopup(event:MouseEvent):void {
PopUpManager.addPopUp(_popup, this, true);
PopUpManager.centerPopUp(_popup);
}
]]>
</fx:Script>
<s:Button id="myBtn" right="5" bottom="5"
label="Open window" click="showPopup(event)" />
</s:Application>
Popup.mxml:
<?xml version="1.0" encoding="utf-8"?>
<s: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"
width="240" height="240"
creationComplete="init(event)"
close="close()">
<fx:Script>
<![CDATA[
import mx.collections.ArrayList;
import mx.controls.Alert;
import mx.events.FlexEvent;
import mx.events.CloseEvent;
import mx.events.ItemClickEvent;
import mx.managers.PopUpManager;
private var myData:ArrayList = new ArrayList();
private function init(event:FlexEvent):void {
// XXX in the real app data is updated from server
myData.removeAll();
for (var i:uint = 1; i <= 10; i++)
myData.addItem('Item #' + i);
}
public function close(event:TimerEvent=null):void {
PopUpManager.removePopUp(this);
}
private function handleClick(event:MouseEvent):void {
var str:String = myList.selectedItem as String;
if (!str)
return;
if (myBox.selected) {
Alert.show(
'Select ' + str + '?',
null,
mx.controls.Alert.YES | mx.controls.Alert.NO,
null,
handleConfirm,
null,
mx.controls.Alert.NO
);
} else {
sendEvent();
}
}
private function handleConfirm(event:CloseEvent):void {
if (event.detail == mx.controls.Alert.YES)
sendEvent();
}
private function sendEvent():void {
close();
// XXX in the real app dispatchEvent() is called
trace('selected: ' + (myList.selectedItem as String));
}
]]>
</fx:Script>
<s:VGroup paddingLeft="20" paddingTop="20"
paddingRight="20" paddingBottom="20" gap="20"
width="100%" height="100%">
<s:List id="myList" dataProvider="{myData}"
click="handleClick(event)"
width="100%" height="100%" fontSize="24" />
<s:CheckBox id="myBox" label="Confirm" />
</s:VGroup>
</s:TitleWindow>
Also I wonder, why do I get the warning above:
Data binding will not be able to detect assignments to "myData".
The Spark List dispatches an 'IndexChangeEvent.CHANGE'. You can listen for this event to know when the selection in the List has changed.
<s:List id="myList" dataProvider="{myData}"
change="handleIndexChange()"
width="100%" height="100%" fontSize="24" />
That event is only dispatched whenever the selected index actually changes, which means that when you reopen the window a second time an item might still be selected and when you click on that one, no CHANGE event will be fired. To fix this just deselect the selection before you close the window:
public function close():void {
myList.selectedIndex = -1;
PopUpManager.removePopUp(this);
}
Also make sure to dispatch your event with the selected item before you close the window (and deselect it).
As for your question about the binding warning: you get that message because you didn't mark 'myData' to be bindable. To fix this just use the [Bindable] tag:
[Bindable]
private var myData:ArrayList = new ArrayList();
or skip the binding altogether if you don't need it and just assign the dataprovider to the list in ActionScript:
myList.dataProvider = myData;
I'd recommend two solutions if you absolutely wnat to display what item was selected. Otherwise, the solution provided by RIAStar would do the trick.
Listen to rendererAdd and rendererRemove events within your PopUp
As explained here, you can easily access to your list's renderers without interfering with its virtualLayout business.
Use a custom renderer
I know. But as long as you keep your code clean, itemRenderers won't blow up your application's memory. They're made to render huge amount of items without memory leaks.
In your Test.mxml, modify the codes like:
<fx:Script>
<![CDATA[
import mx.managers.PopUpManager;
private var _popup:Popup;
private function showPopup(event:MouseEvent):void {
_popup = new Popup();
PopUpManager.addPopUp(_popup, this, true);
PopUpManager.centerPopUp(_popup);
}
]]>
</fx:Script>
And in your Popup.mxml, I am not sure why you have the TimerEvent in the close function.
Also the trace won't be shown, as you are calling the close() function immediately after the alert's YES button has been clicked..

How to refresh an application in Flex?

I have designed a quiz application in Flex 4. At the end I want to reload my application (that is refresh the page in the browser). At the end I will show score in an alert. After that I want to reload the current application. How can I do this?
To cause the refresh to not happen until after your alert is clicked:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark" xmlns:local="*"
>
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.core.FlexGlobals;
import mx.events.CloseEvent;
protected function refreshClicked(event:Event):void
{
Alert.show("Congratulations you won",
"Hooray!",
Alert.NO|Alert.YES, null, refreshFinish);
}
protected function refreshFinish(event:CloseEvent=null):void{
if(event == null){
event = new CloseEvent("refreshFinish");
event.detail = Alert.YES;
}
if(event.detail == Alert.YES){
navigateToURL(new URLRequest(FlexGlobals.topLevelApplication.url), "_self");
}
}
]]>
</fx:Script>
<s:Button label="Alert and Refresh" click="refreshClicked(event)" />
</s:Application>
You can remove the option of "NO" by removing it from the or as the 3rd parameter of Alert.show.
just navigate back to your website :)
navigateToURL(new URLRequest("linktoyourwebsite"));
to get the current page's url, you can use the following code:
import flash.external.ExternalInterface;
var pageURL:String = ExternalInterface.call('window.location.href.toString');
so your code then becomes:
var pageURL:String = ExternalInterface.call('window.location.href.toString');
navigateToURL(new URLRequest(pageURL));
another answer.
we have to call function in AS3
ExternalInterface.call("reload");
in html file within javascript we have to define function reload
function reload()
{
window.location.reload(true);
}

How to set a public var in a popup window?

I am trying to set a variable in a titlewindow pupup and use it in a script section. The variable is not being set and I don't know why.
Here is my Main.mxml file:
<?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" creationComplete="application1_creationCompleteHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import mx.managers.PopUpManager;
protected function application1_creationCompleteHandler(event:FlexEvent):void
{
var test:TestWindow = TestWindow(PopUpManager.createPopUp(this,TestWindow,true));
PopUpManager.centerPopUp(test);
test.testText = 'test 2';
test.bol = true;
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
</s:Application>
Here is my titleWindow file:
<?xml version="1.0" encoding="utf-8"?>
<s: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" width="400" height="300"
close="PopUpManager.removePopUp(this);" creationComplete="titlewindow1_creationCompleteHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import mx.managers.PopUpManager;
[Bindable] public var testText:String = 'test 1';
public var bol:Boolean = false;
protected function titlewindow1_creationCompleteHandler(event:FlexEvent):void
{
if(bol){
trace('Boolean is true');
}
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:Label text='{testText}'/>
</s:TitleWindow>
The problem is the label does change from 'test 1' to 'test 2' but the bol variable will not be set, why is that?
The creationComplete event fires when your TitleWindow has been completely created and only fires once (see component lifecycle).
In your case this happens in your Main.mxml file when you add the pop up with PopUpManager.centerPopUp(test);. bol is getting updated, you're just not seeing that from a trace statement because the creationComplete event has already fired.
If you want to to change the value for bol with your current setup you'll need to do that prior to opening the pop up.
In general I feel that a better way of doing this would be by using getters and setters and data binding (or Flex's invalidation methods which is described in that first link).
Note: these links provided are for Flex 3 but so far as I know all this holds true in Flex 4.
NoobsArePeople2 is 100% correct about what's going on with the lifecycle. A quick and dirty workaround for this is to use PopUpManager.addPopUp() instead of createPopUp():
var test:TestWindow = new TestWindow();
test.testText = 'test 2';
test.bol = true;
PopUpManager.addPopUp(test, this, true);
PopUpManager.centerPopUp(test);
This should allow you to set the values on TestWindow before it actually gets initialized.
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/managers/PopUpManager.html

Resources