Scrollbars in dropdownlist inside DataGrid itemEditor not working - apache-flex

I have a DropDownList inside the itemEditor of my DataGrid. There are enough items in the DropDownList to justify scrollbars. You can see the scrollbars, and the mousewheel works fine. If you move the mouse over the scrollbars, they'll change appearance fine (mouseover is working). If you click on them, the DropDownList closes as if you'd clicked elsewhere in the data grid.
There's a comment on the Adobe Forums that describe the same problem, but it is fairly old and has not been answered.
I've been experimenting with custom skins hoping to find a way to trap the mouse event, but have been unsuccessful.
FWIW, this is Flex4, as an AIR app.
Scratch.mxml (main code)
<?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"
creationComplete="windowedapplication1_creationCompleteHandler(event)">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.events.FlexEvent;
[Bindable] public var dataList:ArrayCollection = new ArrayCollection();
protected function windowedapplication1_creationCompleteHandler(event:FlexEvent):void
{
var o:Object = new Object();
o.theChoice = "abc";
o.choices = new ArrayCollection();
o.choices.addItem("abc");
o.choices.addItem("def");
o.choices.addItem("ghi");
o.choices.addItem("jkl");
o.choices.addItem("mno");
o.choices.addItem("pqr");
o.choices.addItem("stu");
o.choices.addItem("vwx");
o.choices.addItem("yz ");
dataList.addItem(o);
}
protected function col2Label(item:Object, column:DataGridColumn):String {
return item.theChoice;
}
// If you use the labelFunction, then you must specify a sortCompareFunction
private function sortCol2(obj1:Object, obj2:Object):int
{
var d1:String = obj1.col2 as String;
var d2:String = obj2.col2 as String;
if(d1 < d2) {
return -1;
} else if(d1 == d2) {
return 0;
}
return 1;
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<mx:DataGrid id="glGrid" top="10" left="10" right="10" bottom="10"
dataProvider="{dataList}" editable="true" >
<mx:columns>
<mx:DataGridColumn id="col2"
headerText="Column 2"
itemEditor="Renderers.ddlRenderer"
labelFunction="col2Label"
dataField="col2"
sortCompareFunction="sortCol2"/>
</mx:columns>
</mx:DataGrid>
</s:WindowedApplication>
ddlRenderer.mxml:
<?xml version="1.0" encoding="utf-8"?>
<s:MXDataGridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
focusEnabled="true">
<fx:Script>
<![CDATA[
import mx.collections.ArrayList;
import spark.events.IndexChangeEvent;
[Bindable] private var myChoices : ArrayList = new ArrayList();
override public function set data(value:Object):void
{
if (value != null) {
super.data = value;
if (ddl && myChoices) {
myChoices.removeAll();
var theChoice:String = value.theChoice;
myChoices.addAll(value.choices);
var lineChoice : String;
for (var i:int = 0; i < myChoices.length; i++) {
lineChoice = myChoices.getItemAt(i) as String;
if (lineChoice == theChoice) {
ddl.selectedItem = lineChoice;
break;
}
}
}
}
}
]]>
</fx:Script>
<s:DropDownList id="ddl"
width="100%"
dataProvider="{myChoices}"/>
</s:MXDataGridItemRenderer>
To see the problem, run the code, click on "abc" to trigger the itemRenderer, click on the DropDownList to see the choices, then try clicking on the scrollbar.
I'm stumped on this one, and would greatly appreciate some help.
Thanks
Dan

I posted this to Adobe as a bug (SDK-27783, Flex SDK, Spark:DropDownList), which was just closed today. Alex Harui had a good workaround:
Workaround is to change renderer as follows:
<s:DropDownList id="ddl"
width="100%"
dataProvider="{myChoices}" open="ddl.skin['dropDown'].owner = this"/>
I tested this and it solves my problem. Hopefully this will help others as well.

I'm not sure that it's a mouseEvent that you should to trap. You can debug the framework class: DropDownController.as, put a breakpoint at the start of the systemManager_mouseDownHandler function and processFocusOut function. You can see when you clic on the dropdownlist'scrollbar that the systemManager_mouseDownHandler function doesn't call closeDropDown, closeDropDown is called by processFocusOut.
Now add a DropDownList object at the top of your application:
<s:DropDownList id="ddltop"
top="10"
left="10"
width="100%"
dataProvider="{dataList.getItemAt(0).choices}"
/>
<mx:DataGrid id="glGrid" top="50" left="10" right="10" bottom="10"
...
and debug again with the same breakpoints. Now it's the systemManager_mouseDownHandler function that call closeDropDown.
Perhaps the reason for the closure of the dropdownlist.

Related

FlexPrintJob does not print the graphical filters

If I assign filters in the UIComponent.filters property, they display fine on screen, but they are ignored when I print them through FlexPrintJob.
I've tried DropshadowFilter, BlurFilter, BevelFilter. None of them shows up. I tried all the bitmapCaching modes. Also printAsBitmap.
You can try that by going to the example in the ASDoc for FlexPrintJob. Just assign filters to some of the printed components.
Can you show me how to do that?
I put a filter in the first file:
enter code here
FormPrintHeader.mxml
<?xml version="1.0"?>
<!-- Custom control for the header area of the printed page. -->
<s:VGroup name="FormPrintHeader"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
width="60%"
horizontalAlign="right" filters="{[new spark.filters.BlurFilter]}">
<s:Label text="This is a placeholder for first page contents"/>
</s:VGroup>
FormPrintFooter.mxml
<?xml version="1.0"?>
<!-- Custom control for the footer area of the printed page. -->
<s:VGroup name="FormPrintFooter"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
width="60%"
horizontalAlign="right" >
<!-- Declare and initialize the product total variable. -->
<fx:Script>
<![CDATA[
[Bindable]
public var pTotal:Number = 0;
]]>
</fx:Script>
<s:Label text="Product Total: {pTotal}"/>
</s:VGroup>
FormPrintView.mxml
<?xml version="1.0"?>
<!-- Custom control to print the Halo DataGrid control on multiple pages. -->
<s:VGroup name="FormPrintView"
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="*">
<fx:Script>
<![CDATA[
import mx.core.*;
// Declare and initialize the variables used in the component.
// The application sets the actual prodTotal value.
[Bindable]
public var pageNumber:Number = 1;
[Bindable]
public var prodTotal:Number = 0;
// Control the page contents by selectively hiding the header and
// footer based on the page type.
public function showPage(pageType:String):void {
if (pageType == "first" || pageType == "middle") {
// Hide the footer.
footer.includeInLayout = false;
footer.visible = false;
}
if (pageType == "middle" || pageType == "last") {
// The header won't be used again; hide it.
header.includeInLayout = false;
header.visible = false;
}
if (pageType == "last") {
// Show the footer.
footer.includeInLayout = true;
footer.visible = true;
}
//Update the DataGrid layout to reflect the results.
validateNow();
}
]]>
</fx:Script>
<!-- The template for the printed page, with the contents for all pages. -->
<s:VGroup width="80%" horizontalAlign="left">
<s:Label text="Page {pageNumber}"/>
</s:VGroup>
<FormPrintHeader id="header" />
<!-- The data grid. The sizeToPage property is true by default, so the last
page has only as many grid rows as are needed for the data. -->
<mx:PrintDataGrid id="myDataGrid" width="60%" height="100%">
<!-- Specify the columns to ensure that their order is correct. -->
<mx:columns>
<mx:DataGridColumn dataField="Index" />
<mx:DataGridColumn dataField="Qty" />
</mx:columns>
</mx:PrintDataGrid>
<!-- Create a FormPrintFooter control and set its prodTotal variable. -->
<FormPrintFooter id="footer" pTotal="{prodTotal}" />
</s:VGroup>
PrintDataGridExample.mxml
<?xml version="1.0"?>
<!-- Main application to print a Halo DataGrid control on multiple pages. -->
<s:Application name="PrintDataGridExample.mxml"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
initialize="initData();">
<fx:Script>
<![CDATA[
import mx.printing.*;
import mx.collections.ArrayCollection;
import FormPrintView;
import mx.core.FlexGlobals;
// Declare variables and initialize simple variables.
[Bindable]
public var dgProvider:ArrayCollection;
public var footerHeight:Number = 20;
public var prodIndex:Number;
public var prodTotal:Number = 0;
// Data initialization.
public function initData():void {
// Create the data provider for the DataGrid control.
dgProvider = new ArrayCollection;
}
// Fill the dgProvider ArrayCollection with the specified items.
public function setdgProvider(items:int):void {
prodIndex=1;
dgProvider.removeAll();
for (var z:int=0; z<items; z++) {
var prod1:Object = {};
prod1.Qty = prodIndex * 7;
prod1.Index = prodIndex++;
prodTotal += prod1.Qty;
dgProvider.addItem(prod1);
}
}
// The function to print the output.
public function doPrint():void {
var printJob:FlexPrintJob = new FlexPrintJob();
if (printJob.start()) {
// Create a FormPrintView control as a child of the current view.
var thePrintView:FormPrintView = new FormPrintView();
FlexGlobals.topLevelApplication.addElement(thePrintView);
//Set the print view properties.
thePrintView.width=printJob.pageWidth;
thePrintView.height=printJob.pageHeight;
thePrintView.prodTotal = prodTotal;
// Set the data provider of the FormPrintView component's data grid
// to be the data provider of the displayed data grid.
thePrintView.myDataGrid.dataProvider = myDataGrid.dataProvider;
// Create a single-page image.
thePrintView.showPage("single");
// If the print image's data grid can hold all the provider's rows,
// add the page to the print job.
if (!thePrintView.myDataGrid.validNextPage) {
printJob.addObject(thePrintView);
}
// Otherwise, the job requires multiple pages.
else {
// Create the first page and add it to the print job.
thePrintView.showPage("first");
printJob.addObject(thePrintView);
thePrintView.pageNumber++;
// Loop through the following code until all pages are queued.
while (true) {
// Move the next page of data to the top of the print grid.
thePrintView.myDataGrid.nextPage();
thePrintView.showPage("last");
// If the page holds the remaining data, or if the last page
// was completely filled by the last grid data, queue it for printing.
// Test if there is data for another PrintDataGrid page.
if (!thePrintView.myDataGrid.validNextPage) {
// This is the last page; queue it and exit the print loop.
printJob.addObject(thePrintView);
break;
} else {
// This is not the last page. Queue a middle page.
thePrintView.showPage("middle");
printJob.addObject(thePrintView);
thePrintView.pageNumber++;
}
}
}
// All pages are queued; remove the FormPrintView control to free memory.
FlexGlobals.topLevelApplication.removeElement(thePrintView);
}
// Send the job to the printer.
printJob.send();
}
]]>
</fx:Script>
<s:Panel title="DataGrid Printing Example"
width="75%" height="75%"
horizontalCenter="0" verticalCenter="0">
<s:VGroup left="10" right="10" top="10" bottom="10">
<mx:DataGrid id="myDataGrid" dataProvider="{dgProvider}">
<mx:columns>
<mx:DataGridColumn dataField="Index"/>
<mx:DataGridColumn dataField="Qty"/>
</mx:columns>
</mx:DataGrid>
<s:Label width="100%" color="blue"
text="Specify the number of lines and click Fill Grid first. Then you can click Print."/>
<s:TextInput id="dataItems" text="35"/>
<s:HGroup>
<s:Button id="setDP" label="Fill Grid" click="setdgProvider(int(dataItems.text));"/>
<s:Button id="printDG" label="Print" click="doPrint();"/>
</s:HGroup>
</s:VGroup>
</s:Panel>
</s:Application>
Please modify your FormPrintHeader.mxml with below code: -
<?xml version="1.0"?>
<!-- Custom control for the header area of the printed page. -->
<s:VGroup name="FormPrintHeader"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
width="60%"
horizontalAlign="right" xmlns:mx="library://ns.adobe.com/flex/mx"
filters="{[new flash.filters.BlurFilter()]}" creationComplete="addHeaderPrinting(this)">
<fx:Script>
<![CDATA[
import flash.filters.BlurFilter;
import mx.graphics.ImageSnapshot;
private function addHeaderPrinting(source:IBitmapDrawable):void {
var imageBitmapData:BitmapData = ImageSnapshot.captureBitmapData(source);
swfLoader.source = new Bitmap(imageBitmapData);
mylblPrint.includeInLayout = mylblPrint.visible = false;
}
]]>
</fx:Script>
<mx:Label id="mylblPrint"
text="This is a placeholder for first page contents. This is a placeholder for first page contents"/>
<mx:SWFLoader id="swfLoader" >
<mx:filters>
<mx:BlurFilter />
</mx:filters>
</mx:SWFLoader>
</s:VGroup>
Hope this may help you.

4.5 adobe builder/flex eventhandler/skinablepopupcontainer returned data empty

I am new to Flex and am having problems figuring out why this eventlistener always returns null for the event.data. I am trying to implement a simple yes/no prompt for data removal. I have included the skinnable container code and the calling mxml. The alertDB_close handler fires I know that but the event.data is empty. thanks for any suggestions
Main mxml:
protected function button1_clickHandler(event:MouseEvent):void
{
// Create an instance of MyAlertPopUp.
var alertDB:AlertMsgPurge = new AlertMsgPurge();
// Add an event handler for the close event to check for
// any returned data.
alertDB.addEventListener('close', alertDB_closeHandler);
alertDB.open(this, true);
}
private function alertDB_closeHandler(eventP:PopUpEvent):void {
// If commit is false, do data is returned.
rd.text = eventP.data as String;
//return;
/
}
AlertMsgPurge:
<?xml version="1.0" encoding="utf-8"?>
<s:SkinnablePopUpContainer 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[
// //
public function onClick(commit:Boolean):void {
close(true);
}
]]>
</fx:Script>
<s:TitleWindow title="" x="75" y="300">
<s:VGroup horizontalAlign="center" paddingTop="8" paddingBottom="8" paddingLeft="8" paddingRight="8" gap="5" width="100%">
<s:Label text="Warning!! all data will be deleted"/>
<s:Button label="Yes" click="close(true);"/>
<s:Button label="No" click="close(false);"/>
</s:VGroup>
</s:TitleWindow>
With that function modified:
private function alertDB_closeHandler(eventP:PopUpEvent):void {
trace("eventdata:"+eventP.commit);
}
You can see if the user clicked "yes" or "no" then you can do your processing.
Is it what your looking for?

Flex: Row index in Datagrid when 'selectable' is set to 'false'

It would be an easy question, but property 'selectable' is set to 'false' and therefore selectedItem is always null.
In each row I have 3 buttons. When I click a button, I need to extract data corresponding to clicked row.
Any ideas how can I do that? Thanks.
I assume you are using the MX DataGrid, correct?
In your itemRenderer, reference the listData property and convert it to DataGridListData.
When the button is clicked dispatch a custom event that includes the rowIndex. You should be able to use the rowIndex to get the selected item out of your dataProvider.
This is my item renderer
<?xml version="1.0" encoding="utf-8"?>
<s:MXDataGridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
focusEnabled="true">
<fx:Script>
<![CDATA[
public var parentView:Object;
public static function getEditDeleteRenderer(view:Object):ClassFactory{
var editDeleteRenderer:ClassFactory = new ClassFactory(EditDeleteRenderer);
editDeleteRenderer.properties = { parentView:view };
return editDeleteRenderer;
}
function editItem():void{
parentView.editItem(data);
}
function deleteItem():void{
parentView.deleteItem(data);
}
]]>
</fx:Script>
<mx:HBox paddingLeft="5">
<mx:Image source="assets/edit.png" click="editItem()" />
<mx:Image source="assets/delete.png" click="deleteItem()" />
</mx:HBox>
</s:MXDataGridItemRenderer>
This is how I use it
<mx:DataGridColumn headerText="Activity" width="100" itemRenderer="{EditDeleteRenderer.getEditDeleteRenderer(this)}" />
public function editItem(foo:Foo){
// do edit operation
}
public function deleteItem(foo:Foo):void{
// do delete operation
}

Yet another Flex custom events in components question

I can't seem to get one of the most basic uses of events working in Flex 4. I've followed multiple tutorials and looked everywhere. From what I can tell, I'm doing everything right, so there must be some stupid mistake somewhere.
I have a main application file that contains a button. On clicking the button, it fires a custom event which I want my listener in my child component to catch. The event IS firing. The child component event listener is NOT catching that event. No clue why. The custom event is copy-pasted from Adobe's tutorial (minus the custom namespace and comments).
Main Application
<?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"
applicationComplete="init()" xmlns:local="*">
<fx:Metadata>
[Event(name="enableChanged", type="EnableChangeEvent")]
</fx:Metadata>
<fx:Script>
<![CDATA[
import EnableChangeEvent;
import TestComponent;
private function doDispatchEvent(event:MouseEvent):void {
if(dispatchEvent(new EnableChangeEvent(EnableChangeEvent.ENABLE_CHANGED, true)))
{
statusLabel.text = "Event was dispatched";
}
}
public function init():void {
myButton.addEventListener(MouseEvent.CLICK, doDispatchEvent);
}
]]>
</fx:Script>
<s:Button x="95" y="83" label="Button" id="myButton" />
<s:Label x="230" y="83" text="" id="statusLabel" />
<local:TestComponent x="95" y="150" width="300" height="400" />
</s:WindowedApplication>
Child Component (Test)
<?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="100%" height="100%"
initialize="init();">
<fx:Script>
<![CDATA[
import EnableChangeEvent;
private function doFinalAction(event:EnableChangeEvent):void {
myLabel.text = "Custom Event Recieved";
}
private function init():void {
addEventListener(EnableChangeEvent.ENABLE_CHANGED, doFinalAction);
}
]]>
</fx:Script>
<s:Label width="300" height="50" text="Should change on click" id="myLabel" />
</s:Group>
Custom Event (from Adobe)
package {
import flash.events.Event;
public class EnableChangeEvent extends Event
{
public function EnableChangeEvent(type:String, isEnabled:Boolean=false) {
super(type);
this.isEnabled = isEnabled;
}
public static const ENABLE_CHANGED:String = "enableChanged";
public var isEnabled:Boolean;
override public function clone():Event {
return new EnableChangeEvent(type, isEnabled);
}
}
}
Timofei Davydik's answer it correct. Since the Application object dispatches the event, if you want your TestComponent object to catch it, you have to add a listener to a reference of the Application object from within your TestComponent. You can use the TestComponent object's inherited property "parentApplication" to get a reference to the Application object`.
Change the following code in TestComponent.mxml:
private function init():void
{
this.parentApplication.addEventListener(EnableChangeEvent.ENABLE_CHANGED, doFinalAction);
}// end function
[UPDATE]
Personally I feel like your going about using events the wrong way, so I made a similar flex application to demonstrate how to use events in flex.
Main.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"
xmlns:components="components.*"
xmlns:events="events.*"
applicationComplete="init()">
<fx:Script>
<![CDATA[
import events.EnableChangeEvent;
public function init():void
{
label1.text = "Application Complete!";
}// end function
private function onTestButtonEnableChanged(e:EnableChangeEvent):void
{
label2.text = "Enabled = " + e.isEnabled;
}// end function
]]>
</fx:Script>
<s:layout>
<s:VerticalLayout horizontalAlign="center" paddingTop="50" />
</s:layout>
<components:TestButton id="testButton" label="CLICK!" enableChanged="onTestButtonEnableChanged(event)" />
<s:Label id="label1"/>
<s:Label id="label2"/>
</s:WindowedApplication>
TestButton.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Button xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
click="onClick()">
<fx:Metadata>
[Event(name="enableChanged", type="events.EnableChangeEvent")]
</fx:Metadata>
<fx:Script>
<![CDATA[
import events.EnableChangeEvent
private var isEnabled:Boolean;
private function onClick():void
{
isEnabled = !isEnabled;
dispatchEvent(new EnableChangeEvent(EnableChangeEvent.ENABLE_CHANGED, isEnabled));
}// end function
]]>
</fx:Script>
</s:Button>
The main difference between the applications is that the Button object, in this case the TestButton object, dispatches the EnableChangeEvent event when clicked. While dispatching the event we can parse the boolean value for the _isEnabled property of TestButton to the event. Before, the value is inverted using the line isEnabled = !isEnabled. Now we can make use of handling the event using the mxml declaration of the TestButton object with the xml attribute enableChanged.
Also instead of following tutorials you might want to try a book like the one i'm reading. It's called "Adobe Flash Builder 4 and Flex 4 Bible" by David Gassner which you can get as a paperback book or a book for your kindle.
#Taurayi is correct, but to get you current code working with just one change, edit the init of Test Component to look like the following:
private function init():void
{
FlexGlobals.topLevelApplication.addEventListener(EnableChangeEvent.ENABLE_CHANGED, doFinalAction);
}
Your application object dispatches the custom event. Why do you expect your group to "catch" this event? It won't. Custom events have neither capturing nor bubbling phase. So, only listeners added to your application object will listen to this event.

Remove child content from ViewStack in Flex 4

In my example below, when I click "Add Content", new stack content is loaded into the ViewStack as expected. But when I then click "Close Content", I'm expecting it to close the newly created content inside the ViewStack and switch to the "defaultContent" content.
Can anyone tell me where I'm going wrong please? Thanks in advance.
// TestProject.mxml (application)
<?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">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<fx:Script>
<![CDATA[
import com.NewContent;
private function addContent():void
{
var content:NewContent = new NewContent();
var navContent:NavigatorContent = new NavigatorContent();
navContent.id = 'newContent';
navContent.label = 'newContent';
navContent.width = Number('100%');
navContent.height = Number('100%');
navContent.addElement(content);
viewStack.addElement(navContent);
viewStack.selectedChild = navContent;
}
]]>
</fx:Script>
<mx:ViewStack id="viewStack" width="100%" height="100%">
<s:NavigatorContent id="defaultContent"
label="defaultContent">
<s:Button click="addContent()" label="Add Content"/>
</s:NavigatorContent>
</mx:ViewStack>
</s:WindowedApplication>
// NewContent.mxml (component)
<?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="100%" height="100%">
<fx:Script>
<![CDATA[
import mx.core.FlexGlobals;
private function closeContent():void
{
FlexGlobals.topLevelApplication.viewStack.removeChild('newContent');
FlexGlobals.topLevelApplication.viewStack.selectedChild = 'defaultContent';
}
]]>
</fx:Script>
<s:Button click="closeContent()" label="Close Content"/>
</s:Group>
selectedChild expects the child itself, not the label.
Instead - try this:
public function removeContent():void
{
Viewstack(this.parent).selectedIndex = 0;
this.parent.removeChild(this);
}
Note - it's generally reccomended to avoid using FlexGlobals.topLevelApplication, as it leads to a very tightly coupled & fragile application.
Sorted it...
// TestProject.mxml (application)
private function addContent():void
{
var content:NewContent = new NewContent();
content.addEventListener("removeMe",onRemove,false,0,true);
var navContent:NavigatorContent = new NavigatorContent();
navContent.id = 'newContent';
navContent.label = 'newContent';
navContent.width = Number('100%');
navContent.height = Number('100%');
navContent.addElement(content);
viewStack.addElement(navContent);
viewStack.selectedChild = navContent;
private function onRemove(event:Event):void
{
var content:NewContent = event.currentTarget as NewContent;
content.removeEventListener("removeMe",onRemove,false);
viewStack.removeChild(content.parent.parent.parent);
}
// NewContent.mxml (component)
public function removeContent():void
{
dispatchEvent(new Event("removeMe"));
}

Resources