child elements of MXML class not appearing - apache-flex

I'm working on a simple task/calendar tool where tasks can be added dynamically to a canvas. Here is the main application as defined in Main.mxml, which is essentially just a Canvas and a button for adding a task:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Canvas id="MainCanvas" borderStyle="solid" width="300" height="300">
<mx:Button click="CreateTask();" label="create task" />
</mx:Canvas>
<mx:Script>
<![CDATA[
import Task;
private function CreateTask( ) : void
{
// create the task object
var thisTask:Task = new Task();
// add the task to the canvas
var taskUI : DisplayObject = MainCanvas.addChild( thisTask );
// position the task ui
taskUI.y = 50;
}
]]>
</mx:Script>
</mx:Application>
I want my tasks to be BorderContainers with a label and a button, defined in an external mxml, that can simply be instantiated and added to the canvas in Main.mxml. Here is Tasks.mxml:
<?xml version="1.0" encoding="utf-8"?>
<s:BorderContainer xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:s="library://ns.adobe.com/flex/spark" cornerRadius="10">
<s:layout>
<s:HorizontalLayout/>
</s:layout>
<s:Label id="NameLabel" text="task name" />
<s:Button label="Button 1"/>
</s:BorderContainer>
The problem is that when I add a Task instance to the Canvas, the children (the button and label) don't appear. I tried setting creationPolicy="all" on both the Canvas and the BorderContainer, but it still didn't work. I've read a bunch of posts about people having issues accessing members of their class before the class is fully loading, but all I want to do is SEE that Label and Button show up inside the BorderContainer.
Thanks.

You need to move off of the flex 3 mx namespace to the newer namespace if you want to mix mx and spark controls together.
Here's your main.mxml with the new mx namespace (library://ns.adobe.com/flex/mx), and the fx namespace added to handle the script block:
<?xml version="1.0" encoding="utf-8"?>
<mx: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" >
<fx:Script>
<![CDATA[
import Task;
private function CreateTask( ) : void
{
// create the task object
var thisTask:Task = new Task();
// add the task to the canvas
var taskUI : DisplayObject = MainCanvas.addChild( thisTask );
// position the task ui
taskUI.y = 50;
}
]]>
</fx:Script>
<mx:Canvas id="MainCanvas" borderStyle="solid" width="300" height="300">
<mx:Button click="CreateTask();" label="create task" />
</mx:Canvas>
</mx:Application>
Although as other people have commented, you could just move everything over to spark - if you do that, be sure to change the addChild call to addElement.

It appears that adding spark component to an mx:canvas never triggers the code necessary to create the spark component's children. Here is a workaround for you:
<?xml version = "1.0" encoding = "utf-8"?>
<s:BorderContainer
xmlns:mx = "http://www.adobe.com/2006/mxml"
xmlns:s = "library://ns.adobe.com/flex/spark"
cornerRadius = "10"
creationComplete = "{addElement(poorUseOfContainers)}">
<s:HGroup id = "poorUseOfContainers"
width = "100%" height = "100%">
<s:Label id = "NameLabel"
text = "task name" />
<s:Button label = "Button 1" />
</s:HGroup>
</s:BorderContainer>

Related

How do I use data from the main window in a sub-window?

I've just started working on a photo viewer type desktop AIR app with Flex. From the main window I can launch sub-windows, but in these sub-windows I can't seem to access the data I collected in the main window.
How can I access this data?
Or, how can I send this data to the sub-window on creation? It doesn't need to be dynamically linked.
myMain.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"
width="260" height="200"
title="myMain">
<fx:Declarations>
</fx:Declarations>
<fx:Script>
<![CDATA[
public function openWin():void {
new myWindow().open();
}
public var myData:Array = new Array('The Eiffel Tower','Paris','John Doe');
]]>
</fx:Script>
<s:Button x="10" y="10" width="240" label="open a sub-window" click="openWin();"/>
</s:WindowedApplication>
myWindow.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Window name="myWindow"
title="myWindow"
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
width="640" height="360">
<mx:Script>
<![CDATA[
]]>
</mx:Script>
<mx:Label id="comment" x="10" y="10" text=""/>
<mx:Label id="location" x="10" y="30" text=""/>
<mx:Label id="author" x="10" y="50" text=""/>
</mx:Window>
I realize this might be a very easy question but I have searched the web, read and watched tutorials on random AIR subjects for a few days and couldn't find it. The risk of looking like a fool is worth it now, I want to get on with my first app!
You could add an attribute to your window class, and pass the data from the application.
With an attribute and a setter function :
myWindow.mxml :
<![CDATA[
private var _data : Array;
public function set data(data : Array) : void {
this._data = data;
}
]]>
main
<![CDATA[
public function openWin():void {
var w : myWindow = new myWindow();
w.data = myData;
w.open();
}
public var myData:Array = new Array('The Eiffel Tower',
'Paris','John Doe');
]]>
You could also do it by adding a constructor parameter to your window, but you will have to write your Window component in ActionScript.
(Also : you might want to use MyWindow for the name of your component instead of myWindow, but that's just conventionnal nitpicking).
Also, note that there is a singleton variable Application.application that is accessible to all classes in an Application ; however I don't know if this applies to a WindowedApplication, and either way it is not the recommended approach.

Flex: creating a multi column navigation bar for viewstack

I have created a Viewstack and using a Tile component and repeating LinkButtons I was able to make a multi column navigation with the viewstack as the dataprovider. My question is can this be done better? My code is below and I am wondering if I took the long way around this approach.
<?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">
<s:layout>
<s:BasicLayout />
</s:layout>
<fx:Script>
<![CDATA[
import mx.controls.Alert;
private var _listItem:Object;
private var n:int=0;
public function get listItem():Object
{
return this._listItem;
}
public function set listItem(listItem:Object):void
{
try{n++;
this.changeSelection(this._listItem);
}catch(e:Error){}
if(n==1 || n > this.viewStack.length){
this._listItem = listItem;
this.changeSelection(listItem);
}
}
private function setSelection(obj:Object):void{
this.viewStack.selectedIndex = this.viewStack.getChildIndex(this.viewStack.getChildByName(obj.target.getRepeaterItem().name));
this.listItem = obj.target;
}
private function checkSelection(obj:Object):void{
if(obj.target.getRepeaterItem() == this.viewStack.selectedChild){
if(this.listItem != obj.target){
this.listItem = obj.target;
}
}
}
private function changeSelection(obj:Object):void{
if(obj.getRepeaterItem() == this.viewStack.selectedChild){
obj.setStyle("color","#000000");
}else{
obj.setStyle("color","#999999");
}
}
]]>
</fx:Script>
<mx:Tile id="tiles" horizontalGap="20" verticalGap="0" y="210" direction="vertical">
<mx:Repeater id="masterList" dataProvider="{viewStack}">
<mx:LinkButton
id="btn"
label="{masterList.currentItem.label}"
click="this.setSelection(event)"
color="#999999"
creationComplete="checkSelection(event);" />
</mx:Repeater>
</mx:Tile>
<mx:ViewStack id="viewStack" height="200" width="300" backgroundColor="#000000" >
<mx:VBox id="vb1" backgroundColor="#FF0000" label="Screen One"/>
<mx:VBox id="vb2" backgroundColor="#00FF00" label="Screen Two"/>
<mx:VBox id="vb3" backgroundColor="#0000FF" label="Screen Three"/>
<mx:VBox id="vb4" backgroundColor="#00FFFF" label="Screen Four"/>
</mx:ViewStack>
</s:Application>
Looks to me like you've got navigation links that expose different and that those links change color based on which one is selected. Assuming that's the case, it sounds an awful lot like a tab-based navigation model. My approach would be to use the spark TabBar and skin the tabs to look like links. That way you can get rid of most of your code and let the tab skin handle changing the colors based on their current state. Also, you wouldn't need any of the code you have for changing the view stack since the TabBar would handle that for you. Hope that helps.

Passing a parameter from flex main to a flex(4) component with data binding

I have a main mxml file (flex4) and want to pass a parameter (user_name) to a component in a directory called components.
When I run the program, the user_name is NOT being sent from the main to the component file.
(Interestingly, if you make the component visible, you can see the parameter has been passed)
New to flex/actionscript and this parameter passing is (without help) quite a pain to progress.
So, help would be very much appreciated.
TIA.
I have hacked much larger files down to get the following two files:
MAIN
<?xml version="1.0" encoding="utf-8"?>
<s:Application
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:components="components.*">
<mx:Button id="editAccount" label="Edit Account" fontSize="16" color="#000000" x="100" y="125" click="AccountForm(event)" />
<components:editAccountForm visible="false" user_name = "username from main" />
<fx:Script>
<![CDATA[
import components.editAccountForm;
import mx.managers.PopUpManager;
private function AccountForm(e:MouseEvent):void
{
var win3:editAccountForm = new editAccountForm();
PopUpManager.addPopUp(win3,this,true);
PopUpManager.centerPopUp(win3);
}
]]>
</fx:Script>
</s:Application>
COMPONENT FILE
<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical" title="Edit Account Details" x="50" y="600" >
<mx:Form width="100%" height="100%">
<mx:FormItem label="">
<mx:Label width="300" textAlign="center" text="{user_name}"/>
</mx:FormItem>
<mx:FormItem label="Enter your new Email Address">
<mx:TextInput id="email_address2" width="300" maxChars="128" contentBackgroundColor="#F5DC0C"/>
</mx:FormItem>
</mx:Form>
<mx:HBox width="100%" horizontalAlign="center">
<mx:Button id="close" label="Close" click="PopUpManager.removePopUp(this)" />
</mx:HBox>
<mx:Script>
<![CDATA[
[Bindable]
public var user_name:String = "username from Component";
]]>
</mx:Script>
<mx:Script>
<![CDATA[
import mx.core.IFlexDisplayObject;
import mx.events.CloseEvent;
import mx.managers.PopUpManager;
private function closeWindow(e:CloseEvent):void
{
PopUpManager.removePopUp(e.target as IFlexDisplayObject);
}
]]>
</mx:Script>
</mx:TitleWindow>
If you simply want to get the user_name from the main app into your TitleWindow component, just set win3.user_name = user_name after you instantiate win3. If you are looking to bind it to your newly instantiated win3 (which you would do if user_name were expected to change), then you need to look into the BindUtils helper class.
The typical way of getting data back and forth between an app and a dialog is to set the value after you instantiate your dialog, and then add a listener to your dialog so that your app will get notified if something changed. If you are listening for the Close event, for example, you can get the value from the event like so: (event.currentTarget as EditAccountForm).user_name in your app's event handler.
Another common method is to have your window dispatch a custom event (that your main app added a listener to the dialog for) which contains the new value for user_name.
Hope that helps.

How do I create a VBox that will grow to fit all the children rather than use a scrollbar?

I have a Canvas with a VBox in it. As I add items to the VBox, I want the VBox to grow, I want the scrollbar on the Canvas to control the visibility.
How do I accomplish this?
try setting the VBoxes verticalScrollPolicy to off (false? not sure, whatever the negative option is)
Credit to invertedSpear as it was a correct answer, but here's an example that demonstrates it:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
<mx:Script>
<![CDATA[
import mx.controls.Label;
private function createChild() : DisplayObject {
var label:Label = new Label();
label.text = "hello " + container.numChildren;
return label;
}
]]>
</mx:Script>
<mx:Button label="Add More" click="container.addChild(createChild())" />
<mx:Canvas width="100%" height="100%" backgroundColor="#FF0000">
<mx:VBox id="container" verticalScrollPolicy="off" backgroundColor="#FFF" backgroundAlpha="0.5">
<mx:Label text="hello" />
</mx:VBox>
</mx:Canvas>
</mx:Application>

How content dynamically updated in flex

i need your help about below purposes.
problem-1:In php we can easily move one page to another and easily use different type of function from those pages.In flex3 how i can use different type of .mxml pages like php. Please guide me with tutorials.It will really helpful for me.
problem-2: In same page some content dynamically updated its resource by done one task.How can i do that please guide me.
Rather than treating your Flex application as a series of pages, you may want to consider an all-in-one SWF instead. This greatly reduces navigation time, at the cost of a longer initial download. You can switch among different views using tab pages or view stacks. As far as keeping your functions for each page separate, you can do this by implementing each logical "page" as a separate MXML component. Your top-level application MXML would look something like this:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:my="com.mycompany.myapp"
>
<mx:ViewStack id="pageViewStack" width="100%" height="100%">
<my:MyComponent1 width="100%" height="100%"/>
<my:MyComponent2 width="100%" height="100%"/>
</mx:ViewStack>
</mx:Application>
For your second problem I have 2 files
imageResize.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" viewSourceURL="srcview/index.html">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
private var _imageHolderWidth:Number = 500;
private var _imageHolderHeight:Number = 500;
[Bindable]
private var imageArrayCollection:ArrayCollection = new ArrayCollection();
private function changeSize():void{
this.imageHolder.width = this._imageHolderWidth *(this.widthSlider.value * 0.01);
this.imageHolder.height = this.imageHolder.width;
}
private function addToTileList():void{
var bitmapData : BitmapData = new BitmapData(this.imageHolder.width, this.imageHolder.height );
var m : Matrix = new Matrix();
bitmapData.draw( this.imageHolder, m );
this.imageArrayCollection.addItem({bitmapData: bitmapData, width: this.imageHolder.width, height: this.imageHolder.height});
}
]]>
</mx:Script>
<mx:Image id="imageHolder" source="#Embed('fx.png')" />
<mx:HSlider id="widthSlider" width="400" y="520" maximum="100" value="100" minimum="1" labels="[1%, 50%, 100%]" snapInterval="1" change="{changeSize();}" liveDragging="true" />
<mx:Button label="add to tile" click="{this.addToTileList();}"/>
<mx:TileList x="520" dataProvider="{this.imageArrayCollection}" itemRenderer="TileListRenderer" />
</mx:Application>
second file TileListRenderer.mxml:
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="100" height="140">
<mx:Script>
<![CDATA[
import mx.utils.ObjectUtil;
override public function set data(value:Object):void
{
super.data = value;
}
]]>
</mx:Script>
<mx:VBox horizontalAlign="center">
<mx:Image id="thumbHolder" source="{new Bitmap(data.bitmapData)}" maxWidth="100" maxHeight="100" />
<mx:Label text="{data.width}x{data.height}" />
</mx:VBox>
</mx:Canvas>
Because it is easier to see it with working source (right mouse button to see the source):
blog.arnomanders.nl/upload/imageResize/imageResize.html

Resources