I have a parent w/ a popup child. When parent loads, I have to call a function within the popup without showing the popup (thus, I load "pupLove" but don't include it in layout)....I then pass this data to the parent. When the user manually clicks another button to open the popup, the same function is called & data passed to the parent. However, I am not able to pass dg.length to the parent. I believe the root problem is that I am loading "pupLove" & thus the parents are getting confused.....I'm guessing if I get rid of "pupLove" I can pass the data correctly but will need to call the child's function at creationComplete of the parent....how do I do that?
Here's my parent:
<?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"
backgroundColor="green" width="50%" height="100%"
xmlns:local="*"
>
<fx:Script>
<![CDATA[
import pup;
import mx.managers.PopUpManager;
public function showPup(evt:MouseEvent):void {
var ttlWndw:pup = PopUpManager.createPopUp(this, pup, true) as pup;
PopUpManager.centerPopUp(ttlWndw);
}
]]>
</fx:Script>
<mx:VBox>
<local:pup id="pupLove" visible="false" includeInLayout="false" />
<s:Button click="showPup(event);" label="launch Pup" />
<mx:Text id="Ptest" color="black" text="from Parent:{pupLove.dg.length}" />
</mx:VBox>
</s:Application>
And a popup child called 'pup.mxml':
<?xml version="1.0" encoding="utf-8"?>
<s:Group 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[
public function init():void{
// send php call
}
import mx.events.CloseEvent;
import mx.managers.PopUpManager;
private function removePup(evt:Event):void {
PopUpManager.removePopUp(this);
}
]]>
</fx:Script>
<fx:Declarations>
<s:ArrayCollection id="dg">
</s:ArrayCollection>
</fx:Declarations>
<s:TitleWindow width="100%" height="100%" close="removePup(event)">
<mx:VBox>
<mx:Text id="test" color="red" text="from Child:{dg.length}" />
<s:Button label="add Items" click="dg.addItem({id:'cat'})" />
</mx:VBox>
</s:TitleWindow>
</s:Group>
UPDATE: I guess my question can be more easily stated as: "is there a way to call a child's function from the parent without actually loading the child?"
Well, if in your child's function, you don't need to access any of its UI component, then you could instanciate the child in the parent view and call the method.
When you need to display the popup afterwhile, use the PopupManager addPopup method with this existing instance instead of using createPopup
Related
I used my app's resize handler to resize my component but it is throwing this error :
TypeError: Error #1009: Cannot access a property or method of a null object reference
Here is my 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="955" minHeight="600"
resize="application2_resizeHandler(event)" >
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import mx.events.ResizeEvent;
private var employeeName:String = 'ravi';
protected function application2_resizeHandler(event:ResizeEvent):void
{
mainGroup.width = stage.width - 10;
mainGroup.x = 5;
}
]]>
</fx:Script>
<s:Group width="100%" height="100%">
<s:VGroup id="mainGroup" >
<s:Label id="employeeNameLabel" text="{employeeName}" />
<s:Label id="departmentLabel" />
</s:VGroup>
<s:Button id="getData" />
</s:Group>
</s:Application>
You got the #1009 error because your resize event is fired before the creation of your objects. So, you should wait for that and that your app is added to the stage to be able to use the stage object.
For that, I think that the best event is the applicationComplete event, then you can add a resize event to resize your component ...
So you can do like this for example :
<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"
applicationComplete="application2_applicationCompleteHandler(event)" >
then
protected function application2_applicationCompleteHandler(event:FlexEvent):void
{
// if you want you can resize your component for the 1st time
// by calling the application2_resizeHandler() function
application2_resizeHandler(new ResizeEvent(ResizeEvent.RESIZE));
// add the resize event listener to your app
event.target.addEventListener(ResizeEvent.RESIZE, application2_resizeHandler);
}
Hope that can help.
I have a simple application:
<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:local="*">
<mx:ViewStack width="100%" creationPolicy="all">
<s:NavigatorContent width="100%">
<local:TestGroup width="100%"/>
</s:NavigatorContent>
<s:NavigatorContent width="100%">
<local:TestGroup width="100%"/>
</s:NavigatorContent>
</mx:ViewStack>
</s:Application>
My TestGroup is a bare Spark group. It has creationComplete method, where the width of the group is traced:
<s:Group 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="group1_creationCompleteHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
protected function group1_creationCompleteHandler(event:FlexEvent):void
{
trace("internal group width: " + this.width)
}
]]>
</fx:Script>
</s:Group>
When I run the application, the first TestGroup has width of 1600 (which is about right), but the second one regardless of creationPolicy="all" and width="100%" is 0 (zero).
It turs out that ms:ViewStack doesn't set width for components other than the selected one.
What is the logic behind this behavior?
How can I fix it so that my second group has a real width, and I can get it at the creation complete?
You can listen to change event, that will be fired each time the selected group is changing.
Only the current active group will give you her true width, so you can do someThing like this
<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:local="*">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
protected function onChange(event:Event):void
{
if(myViewStack.selectedChild){
myViewStack.selectedChild.initMyGroup();
}
}
]]>
</fx:Script>
<mx:ViewStack id="myViewStack" width="100%" creationPolicy="all" change="onChange()">
<s:NavigatorContent width="100%">
<local:TestGroup width="100%"/>
</s:NavigatorContent>
<s:NavigatorContent width="100%">
<local:TestGroup width="100%"/>
</s:NavigatorContent>
</mx:ViewStack>
</s:Application>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
public function initMyGroup():void
{
trace("internal group width: " + this.width)
}
]]>
</fx:Script>
</s:Group>
The ViewStack is a Multiple-view container. Even though having the creationComplete set to all which is by the way for Single-view containers only, Flex instantiates only the controls that are initially visible for the ViewStack. To achieve your goal, try using other containers aside from ViewStack.
More details can be found here:
http://livedocs.adobe.com/flex/3/html/help.html?content=layoutperformance_05.html
What is the logic behind this behavior?
Because there is no need to render a TestGroup element. If you set creationPlicy for all a flex container will create internal element, but it doesn't mean that the container will set size for the element.
How can I fix it so that my second group has a real width, and I can get it at the creation complete?
Use event updateComplete. Flex dispatches updateComplete events whenever the layout, position, size, or other visual characteristic of the component changes and the component is updated for display. So you will get it when second TestGroup will be selected first time.
I have an AdvancedDataGrid (whose dataProvider is a variable being bound from my main mxml file, not sure if this is relevant to my problem ). I'm setting one of the AdvancedDataGridColumn's editable property as true, and when I click on the cell in the UI, it is infact editable. But when I press enter/move to a different cell, the old value returns and the newly entered value is lost. Would anyone have any ideas why that's happening? Do I have to manually change the variable provided in the dataProvider?...I would think that would happen automatically right? I'd appreciate any help!
Thanks.
This traces out correct when I edit a field and press enter then click on the button to see trace output:
<?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" applicationComplete="init()">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.collections.HierarchicalData;
[Bindable]
private var companyHierarchy:HierarchicalData;
private var companyData:XML = <data>
<company name="Employees">
<department name="Unit 1">
<employee name="Dave" func="C# Developer"/>
<employee name="Bob" func="AS3 Developer"/>
<employee name="Clair" func="AS3 Architect"/>
</department>
<department name="Unit 2">
<employee name="John" func="ORACLE Developer"/>
<employee name="Sandra" func="HTML Developer"/>
</department>
</company>
</data>;
private function init():void
{
companyHierarchy = new HierarchicalData(companyData.company);
}
private function checkSetData():void
{
trace(companyData);
}
]]>
</fx:Script>
<mx:AdvancedDataGrid id="test" width="500" height="500" dataProvider="{companyHierarchy}"
displayItemsExpanded="true" editable="true" enabled="true">
<mx:columns>
<mx:AdvancedDataGridColumn dataField="#name"
headerText="Companies"/>
<mx:AdvancedDataGridColumn dataField="#func"
headerText="Function"/>
</mx:columns>
</mx:AdvancedDataGrid>
<s:Button x="205" y="508" label="Button" click="checkSetData()"/>
</s:Application>
Here is my code.
<?xml version="1.0" encoding="utf-8"?>
<fx:Script>
<![CDATA[
import comps.sampleTextArea;
import mx.managers.PopUpManager;
protected function button1_clickHandler(event:MouseEvent):void
{
var pop:sampleTextArea = new sampleTextArea();
PopUpManager.createPopUp(this, sampleTextArea, false);
PopUpManager.centerPopUp(pop);
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:Button click="button1_clickHandler(event)" label="open popup"/>
and here is code of popup
<?xml version="1.0" encoding="utf-8"?>
<fx:Script>
<![CDATA[
import mx.managers.PopUpManager;
protected function button1_clickHandler(event:MouseEvent):void
{
ta.text = '';
PopUpManager.removePopUp(this);
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:layout>
<s:VerticalLayout horizontalAlign="center" verticalAlign="top" />
</s:layout>
<s:TextArea id="ta" width="100%" height="90%">
</s:TextArea>
<s:Button label="Submit" click="button1_clickHandler(event)" />
when i click on text area following error through by the application.
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at spark.components::Scroller/focusInHandler()[E:\dev\4.y\frameworks\projects\spark\src\spark\components\Scroller.as:2139]
at flash.display::Stage/set focus()
at flashx.textLayout.container::ContainerController/http://ns.adobe.com/textLayout/internal/2008::setFocus()[C:\Vellum\branches\v2\2.0\dev\output\openSource\textLayout\src\flashx\textLayout\container\ContainerController.as:2265]
at flashx.textLayout.container::ContainerController/mouseDownHandler()[C:\Vellum\branches\v2\2.0\dev\output\openSource\textLayout\src\flashx\textLayout\container\ContainerController.as:2067]
at flashx.textLayout.container::TextContainerManager/mouseDownHandler()[C:\Vellum\branches\v2\2.0\dev\output\openSource\textLayout\src\flashx\textLayout\container\TextContainerManager.as:1939]
at spark.components.supportClasses::RichEditableTextContainerManager/mouseDownHandler()[E:\dev\4.y\frameworks\projects\spark\src\spark\components\supportClasses\RichEditableTextContainerManager.as:666]
at flashx.textLayout.container::ContainerController/http://ns.adobe.com/textLayout/internal/2008::requiredMouseDownHandler()[C:\Vellum\branches\v2\2.0\dev\output\openSource\textLayout\src\flashx\textLayout\container\ContainerController.as:2088]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at mx.core::UIComponent/dispatchEvent()[E:\dev\4.y\frameworks\projects\framework\src\mx\core\UIComponent.as:13152]
at mx.managers::SystemManager/mouseEventHandler()[E:\dev\4.y\frameworks\projects\framework\src\mx\managers\SystemManager.as:2918]
How i handle this issue
try, because this refer to stage no the clicked element:
PopUpManager.removePopUp(event.target);
You may not be able to popup a focusable component inside a
non-IFocusManagerContainer. If your Group container implements IFocusManagerContainer class, you may use PopUpManager.
<s:Group implements="mx.managers.IFocusManagerContainer"/>
I ran into the same issue, and the root cause was that PopUpManager/PopUpAnchor would not properly set the focusManager if the component being popped up does not implement the IFocusManagerContainer interface. After implementing such interface, the problem goes away.
You may read this blog post that inspired the solution.
After doing many experiments/ways i conclude that problem is due to the popup component parent container.
I use Group/VGroup/HGroup of spark then this issue remains but if i change the parent container with spark Panel/SkinnableContainer then issue solved.
Try yourself and enjoy.
I've got the latest Beta of Adobe Flash Builder 4.
I want to use a <s:List> component, and specify the dataProvider as being an XML file.
However, after loads of research (including looking at doc links off labs.adobe.com), I still can't figure out how to do it.
The XML file will look something like this:
<?xml version="1.0" encoding="ISO-8859-1"?>
<imageList>
<image location="path/to/file1.jpg" />
<image location="path/to/file2.jpg" />
<image location="path/to/file3.jpg" />
</imageList>
if you want to display images in a list, you should load the xml with a URLLoader , store it in a bindable variable and assign that as data provider to your list. the list should use a mx:itemrenderer where you can customize your view as you wish.
Actual code goes someting like this
<fx:Script>
<![CDATA[
import mx.collections.XMLListCollection;
import mx.collections.IList;
import mx.controls.Image;
private var loader : URLLoader = new URLLoader();
[Bindable]
private var xml : XMLList;
private function init() : void
{
this.loader.addEventListener(Event.COMPLETE, onComplete);
this.loader.load(new URLRequest("data.xml"));
}
private function onComplete(evt : Event) :void
{
this.loader.removeEventListener(Event.COMPLETE, onComplete);
this.xml = new XML(this.loader.data).image;
}
]]>
</fx:Script>
<mx:List id="list" width="200" height="500" dataProvider="{xml}">
<mx:itemRenderer>
<fx:Component>
<mx:Image width="200" height="200" source="{data.#location}" />
</fx:Component>
</mx:itemRenderer>
</mx:List>
If you want to load the XML file over the network you can do:
<?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/halo">
<fx:Declarations>
<mx:HTTPService id="srv" url="http://ws.jamesward.com/images.xml"/>
</fx:Declarations>
<s:applicationComplete>
srv.send();
</s:applicationComplete>
<s:List dataProvider="{srv.lastResult.images.image}" width="100%" height="100%">
<s:itemRenderer>
<fx:Component>
<mx:Image source="{data.source}"/>
</fx:Component>
</s:itemRenderer>
</s:List>
</s:Application>
You need to use the XMLListCollection class.
<s:List dataProvider="{new XMLListCollection(data.image)}" labelField="#location"/>
My original aim was to have an XML file external to the SWF that my client could maintain themselves, and thus they would have control over the images displayed.
The first answer I posted was not quite the solution I was after: using fx:XML means that the contents of the XML file is actually compiled into the SWF, and hence is not alterable after compilation.
So I've implemented James' solution.
The XML file looks like this:
<?xml version="1.0" encoding="ISO-8859-1"?>
<images>
<image source="path/to/image1.jpg" />
<image source="path/to/image2.jpg" />
<image source="path/to/image3.jpg" />
<image source="path/to/image4.jpg" />
</images>
MXML:
<?xml version="1.0" encoding="utf-8"?>
<s:Group
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/halo"
>
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
protected function lstImages_creationCompleteHandler(event : FlexEvent) : void
{
dpHttpService.send();
}
]]>
</fx:Script>
<fx:Declarations>
<mx:HTTPService
id="dpHttpService"
url="images.xml"
/>
</fx:Declarations>
<s:List
id="lstImages"
dataProvider="{dpHttpService.lastResult.images.image}"
width="100%"
itemRenderer="path.to.render.ImageRenderer"
skinClass="path.to.skins.ListSkin"
>
<s:layout>
<s:HorizontalLayout gap="2" />
</s:layout>
</s:List>
</s:Group>
And in the image renderer, I refer to the data like this:
<mx:Image
id="imgRendered"
source="{data.source}"
/>
The really useful thing about this solution is that I can also put full http:// references to images that exist on another site if I want to (remembering crossdomain.xml, of course).
In fact, the images.xml file can exist on another server.
Well, I found one solution.
The MXML will look like this:
<fx:Declarations>
<fx:XML
id="dpXml"
source="path/to/images.xml"
/>
<mx:XMLListCollection
id="dpXmlListCollection"
source="{dpXml.image}"
/>
</fx:Declarations>
<s:List
id="lstImages"
dataProvider="{dpXmlListCollection}"
itemRenderer="path.to.render.ImageRenderer"
skinClass="path.to.skins.ListSkin"
>
<s:layout>
<s:HorizontalLayout gap="2" />
</s:layout>
</s:List>
And images.xml like this:
<?xml version="1.0" encoding="ISO-8859-1"?>
<images>
<image>
<location>path/to/image1.jpg</location>
</image>
<image>
<location>path/to/image2.jpg</location>
</image>
<image>
<location>path/to/image3.jpg</location>
</image>
</images>
Many thanks for all your responses!
Matt