Calling Application.application.enable from a TitleWindow in a different mxml component - apache-flex

I have a Flex RIA App, and in the application tag there is a button when it's pressed calls upon a TitleWindow from another .mxml file, and sets
application.enable = false
That way the user can't use any of the components in the application, and still can use the components in the TitleWindow.
The problem is when the TitleWindow is closed I want it to restore the application back to
application.enable = true
Which enables the application once again. But I can't call that code from inside the TitleWindow .mxml
How can I do it?
Here is the Source:
Loja.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="585" height="450" xmlns:ns1="com.*">
<mx:Style source="theme/simplicitygray.css" />
<mx:Script>
<![CDATA[
import mx.managers.PopUpManager;
private var clientid = 0;
public function openWindow() : void
{
if (clientid == 0)
{
PopUpManager.createPopUp(this,Login,false);
application.enabled = false;
} else {
PopUpManager.createPopUp(this,Conta,false);
application.enabled = false;
}
}
]]>
</mx:Script>
<mx:Panel x="10" y="40" width="565" height="400" layout="absolute">
</mx:Panel>
<mx:MenuBar x="10" y="10" width="565" height="22"></mx:MenuBar>
<mx:Button x="508" y="10" label="Aceder" click="openWindow();"/>
</mx:Application>
And one of the title windows. Once they are the same.
Login.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="350" height="200" creationComplete="centerWindow()" showCloseButton="true" close="closeWindow()" title="Login">
<mx:Script>
<![CDATA[
import mx.managers.PopUpManager;
public function centerWindow():void
{
PopUpManager.centerPopUp(this);
}
public function closeWindow():void
{
PopUpManager.removePopUp(this);
}
]]>
</mx:Script>
</mx:TitleWindow>

application is a static property of the Application class and can be called from the TitleWindow
public function closeWindow():void
{
PopUpManager.removePopUp(this);
Application.application.enabled = true;
}
BTW, There is another easier way to achieve the following:
That way the user cant use any of the components in the application, and still can use the components in the TitleWindow.
That is to use a modal popup. Set the third parameter of the createPopUp to true and that's it - you don't have to enable/disable the application manually: flex will take care of it.
PopUpManager.createPopUp(this,Login, true);
application will automatically become functional once you call removePopUp.

You can use custom events to enable this functionality, as described here.
Essentially, you set up a custom event in the class you are calling, then create a function that runs when the event is consumed. That way your 'Loja' will know when the 'Login' is done.

Related

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..

using an image item render in a flex data grid

I'm attempting to add an image to a datagrid item render dynamically in flex.
Here is my DataGrid code
The value of "str" in the getImagePath function is correct.
<?xml version="1.0" encoding="utf-8"?>
<mx:DataGrid xmlns:mx="http://www.adobe.com/2006/mxml"
doubleClickEnabled="true">
<mx:Script>
<![CDATA[
private function userLabelFunction(item:Object, column:DataGridColumn):String
{
return item.user.username;
}
private function getImagePath(item:Object, column:DataGridColumn):String
{
var str:String=item.track["artwork-url"]
if (str == "")
{
str=item.user["avatar-url"];
}
return str;
}
]]>
</mx:Script>
<mx:columns>
<mx:DataGridColumn dataField="artwork-url"
headerText="Art"
itemRenderer="components.content.contents.datagrids.ImageRenderer"
labelFunction="getImagePath"/>
<mx:DataGridColumn dataField="title"
headerText="Title"
minWidth="100"/>
<mx:DataGridColumn dataField="user"
headerText="User"
labelFunction="userLabelFunction"/>
<mx:DataGridColumn dataField="bpm"
headerText="BPM"/>
</mx:columns>
</mx:DataGrid>
I cant manage to get that image url value into my item renderer
I've tried overriding the set data property like so
<?xml version="1.0" encoding="utf-8"?>
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml"
height="60"
verticalAlign="top"
creationComplete="init()">
<mx:Script>
<![CDATA[
import components.content.contents.containers.ContentContainerSoundCloud;
import mx.core.Application;
import mx.controls.dataGridClasses.DataGridColumn;
import com.adobe.viewsource.ViewSource;
[Bindable]
public var imgPath:String;
private function init():void
{
}
override public function set data(value:Object):void
{
super.data = value.track["artwork-url"];
imgPath =super.data.valueOf()
trace(imgPath)
}
]]>
</mx:Script>
<mx:Image source="{imgPath}" id="rowimage"/>
</mx:HBox>
But in doing so the trace output looks like so
<artwork-url>
<mx_internal_uid>7C98E149-1984-584C-7600-AD8940BF2A9C</mx_internal_uid>
</artwork-url>
I was expecting the "value" property in the set data to recieve the string I sent it from the get imagePathFunction but it fact it returns my entire XMLList.
What am I doing wrong?
Based on your trace output it looks like you are retrieving the wrong value from your dataProvider to set as the source. Without seeing your actual data, it's hard to know what the exact issue may be.
That said, I would re-work your itemRenderer a bit. First, you don't need to put a single image in an HBox. Just use an Image. Also, you should not need to specify the height in the Renderer, the DataGrid should take care of such positioning.
I also removed the creationComplete listener, since no code was in it. And instead of using binding, I just set the soruce property on the component in the data set method. I also set the super.data to the value, not a processed value; and I performed the processing when setting the value's source. The updated code is like this:
<?xml version="1.0" encoding="utf-8"?>
<mx:Image xmlns:mx="http://www.adobe.com/2006/mxml"
>
<mx:Script>
<![CDATA[
import components.content.contents.containers.ContentContainerSoundCloud;
import mx.core.Application;
import mx.controls.dataGridClasses.DataGridColumn;
import com.adobe.viewsource.ViewSource;
[Bindable]
public var imgPath:String;
override public function set data(value:Object):void
{
super.data = value;
this.source =value.track["artwork-url"];
trace(imgPath)
}
]]>
</mx:Script>
</mx:Image>
My preferred method in itemRenderers is to listen to the dataChange event, however that's just personal preference. There is nothing wrong w/ overriding the data set method.

flex custom events bubbling

Dear Richard Szalay,
i go through your answers regarding bubbling, i want explore bubbling more.
Please see my sample below
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:view="com.view.*" >
<mx:Script>
<![CDATA[
import com.events.ImgLoaded;
private function loadedd(evt:ImgLoaded):void{
trace("test")
evt.stopImmediatePropagation();
}
private function panelClickHandler(evt:Event):void{
trace("panel");
}
]]>
</mx:Script>
<mx:VBox>
<mx:Panel click="panelClickHandler(event)">
<view:Load imgLoad="loadedd(event)"/>
</mx:Panel>
</mx:VBox>
</mx:Application>
In my custom event class i set bubbling=true, cancelable=true
I can understand from previous answer that bubbling only affects UI components; events fired from custom classes will not bubble, even if the bubbles argument is set to true.
My question is how can i prevent panelClickHandler function got fired when i click button in the "Load" (custom component)??
please explain bubbling with good example ( like to have with custom event classes)?
I assume your first language isn't english and at any rate I am not sure I fully understand you, but what I think you are asking for is how to allow for a click in the view:load from firing the click handler on the panel.
What you need is to set up an event listener for a click on the view:load component, and stopPropagation from there. That will prevent the click handler on the panel from firing. Example:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:view="com.view.*" >
<mx:Script>
<![CDATA[
import com.events.ImgLoaded;
private function loadedd(evt:ImgLoaded):void{
trace("test")
evt.stopImmediatePropagation();
}
private function panelClickHandler(evt:Event):void{
trace("panel");
}
private function load_clickHandler ( e:MouseEvent ) : void
{
e.stopPropagation;
}
]]>
</mx:Script>
<mx:VBox>
<mx:Panel click="panelClickHandler(event)">
<view:Load imgLoad="loadedd(event)" click="load_clickHandler(event)"/>
</mx:Panel>
</mx:VBox>
</mx:Application>

Why wouldn't a flex remoteobject be able to work within a custom component?

Please enlighten this flex noob. I have a remoteobject within my main.mxml. I can call a function on the service from an init() function on my main.mxml, and my java debugger triggers a breakpoint. When I move the remoteobject declaration and function call into a custom component (that is declared within main.mxml), the remote function on java-side no longer gets called, no breakpoints triggered, no errors, silence.
How could this be? No spelling errors, or anything like that. What can I do to figure it out?
mxml code:
&#060 mx:RemoteObject id="myService"
destination="remoteService"
endpoint="${Application.application.home}/messagebroker/amf" &#062
&#060 /mx:RemoteObject &#062
function call is just 'myService.getlist();'
when I move it to a custom component, I import mx.core.Application; so the compiler doesn't yell
my child component: child.mxml
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init()" >
<mx:Script>
<![CDATA[
import mx.core.Application;
public function init():void {
helloWorld.sayHello();
}
]]>
</mx:Script>
<mx:RemoteObject id="helloWorld" destination="helloService" endpoint="$(Application.application.home}/messagebroker/amf" />
<mx:Label text="{helloWorld.sayHello.lastResult}" />
</mx:Panel>
my main.mxml:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init()" xmlns:test="main.flex.*" >
<mx:Script>
<![CDATA[
[Bindable]
public var home:String;
[Bindable]
public var uName:String;
public function init():void {
//passed in by wrapper html
home = Application.application.parameters.appHome;
uName = Application.application.parameters.uName;
}
]]>
</mx:Script>
<test:child />
</mx:Application>
The child components are calling creationComplete before the parent (so home is null). A solution is to throw an event (like InitDataCompleted) from the parent after you read the data, and in the child components listen for this event (so don't rely on creationcomplete in the child).
However more important than that is how can you diagnose in future this kind of problems. A simple tool like a proxy (eg Charles) should help.
For your endpoint value you've got
endpoint="$(Application.application.home}/messagebroker/amf"
Why are you using $( before Application.application... This should be a { as in:
endpoint="{Application.application.home}/messagebroker/amf"

Flex : Problem with instantiating an mxml component

I have two mxml files in a flex project:
But when I trace a.cBtn, it is null.
Why should it be?
test.mxml :
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="runIt()">
<mx:Script>
<![CDATA[
public function runIt():void
{
var a:abc = new abc();
trace(a.cBtn);//a.cBtn is null here
}
]]>
</mx:Script>
</mx:Application>
And, abc.mxml :
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300">
<mx:Button x="108" y="73" label="Button" id="cBtn"/>
</mx:Canvas>
The underlying issue here is that in Flex, the children components of a given flex container component are not created until that container is initialized. The initialization process starts after you add the container to the display list. As noted above, the CREATION_COMPLETE event is fired after initialization is done and the children are instantiated, so you can safely access children at that point.
It's pretty ugly, but if you absolutely need to access the children of a component before you want to add that component to the display list, you can call "initialize()" on your container.
public function runIt():void
{
var a:abc = new abc();
trace(a.cBtn);//a.cBtn is null here
a.initialize();
trace(a.cBtn);//a.cBtn is not null here
}
You need to wait for the creationcomplete event.
public function runIt():void
{
var a:abc = new abc();
a.addEventListener(FlexEvent.CREATION_COMPLETE, traceIt)
trace(a.cBtn);//a.cBtn is null here
}
private function traceIt(e:Event):void
{
trace(a(e.target).cBtn)
}

Resources