Access the public, bindable variable from one .MXML in another .MXML - apache-flex

I have as a main application setted "main.mxml"
which contains the follow declaration :
[Bindable]
[Embed(source="../images/common/user.png")]
public var userIcon : Class;
I have another module, on which i wish to access it as a button icon.
I have tried with the follow definition, but it doesnt work:
<s:Group width="100%" height="29">
<s:layout>
<s:VerticalLayout horizontalAlign="center"/>
</s:layout>
<s:Button id="buttonLoad" width="80%" label="Loading" icon="{ main.userIcon }"/>
</s:Group>
How to access the declaration inside main.mxml from the other modules ?

The name of MXML class isn't an identifier of its instance (because of it can have a lot of instances). You should think about MXML files as not files but classes. They are absolutely the same as ordinary ActionScript classes. The same rules as in other OOP languages. So if you have main.mxml main is a class name for that class and its package is determined by that MXML file path relative to the source folder (as in ActionScript classes). That's why you should name your MXML classes from the capital letter (Main.mxml but not main.mxml).
If your main.mxml is top level application you can refer it as FlexGlobals.topLevelApplication. But it is not the right way to do things.
The best way is to inject this property to your target class. You can do it using Dependency Injecting Framework/Container like Spring ActionScript or RobotLegs or Parsley. Or you can do it manually by delegating from top application to the class containing piece of code which handles modules. When module is loaded pass this value there.

Related

Is it possible to create skinnable components in MXML using the Spark component architecture?

There are lots of examples of how to create skinnable components in AS3 using the new Spark component architecture, however I've yet to find any such examples using MXML.
What I'm mainly referring to is defining the skin parts and skin states. It seems as though the SkinPart metadata is supposed to be associated with properties and as such can't be used in MXML, is this correct?
As far as I can tell, this isn't possible, because - as you rightly pointed out, there's no way to assign property-level metadata in MXML.
But declaring skin contracts in MXML seems like it would go against the spirit of the Skinning architecture, which is to separate the view of the component from it's implementation logic.
And, given that in MXML everything declared has a value, it inherently couples the component to a skin.
Ie:
<!-- labelDisplay has a value -->
<s:Label id="labelDisplay" />
vs
[SkinPart]
public var labelDisplay:Label; // labelDisplay == null;
Likewise, most of the component logic itself would end up in a <fx:Script /> block, which would probably be better suited in a seperate class.

How to switch between different applications(mxml file with Application as the root tag) in a big Flex application?

I'm new to flex. Now I'm writing an flex application. I plan to split my application into some MXML files(Application as the root tag). How can I switch from one mxml to another?
BTW, what is the best practice for design large flex application? Just one MXML Application and many MXML component or many MXML Application?
Thanks!
Its always advisable to create application with many mxml files.
that will allow to modularize the application.
you will be anyway have one main application file and many sub mxml files, which you will add as children to the main app file. splitting application into sub files will keep your code short for each file and development becomes faster. when the file size increases flex builder performance downgrades. also modularising of code will reduce the end swf file size as well the time required to load the application.
you can have one main application file and include the child mxml components like the following.
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
backgroundColor="white"
xmlns:components="components.*">
<mx:HBox width="100%" height="100%" left="10" right="10" top="10" bottom="10">
<mx:VBox width="100%" height="100%">
<components:component1 id="comp1"/>
<components:component2 id="comp2"/>
</mx:VBox>
<components:component3 id="comp3"/>
</mx:HBox>
</mx:Application>
Here component1, component2 and component3 are three different mxml files and they are stored in the folder 'components' under 'src'. the folder is declared in the namespace 'components' in the application root tag. this is how you can include the child components using mxml. for including using actionscript you can use the method 'addChild'.
Cheers,
PK

Is there a way to truly extend a Flex component?

I need to create an extension of a Flex component, which (obviously) means that the new component should be able to be used whenever the parent is used. But I don't see the way to do it, Flex offers two ways of extending a component, by defining an AS class extending the parent or by creating an MXML file that uses the parent component as a root element; in both cases I can’t use nested elements to configure the child as I do for parent.
E. G.
package components {
import mx.controls.AdvancedDataGrid;
public class FixedDataGrid extends AdvancedDataGrid {
public function FixedDataGrid() {
super();
}
}
}
This is Valid MXML
<mx:AdvancedDataGrid>
...
<mx:columns>
...
This is NOT Valid MXML
<mx:FixedDataGrid>
...
<mx:columns>
...
It doesn't seem like a valid is-a relation.
Your FixedDataGrid doesn't exist in the same namespace as the mx components...
you need to specify the correct namespace for it to be legal.
<mx:Application xmlns:components="components.*" ... >
<components:FixedDataGrid>
....
You are doing the mxml equivalent of declaring your component in the components package then complaining you can't reference it as mx.controls.FixedDataGrid
When defining properties via a new MXMLtag, the property must contain be specified in the same namespace as the tag.
So you could do something like this:
<myComp:FixedDataGrid columns="SomeArray">
Without any issues. If you use the MXML tag syntax to define the columns array property, you need to do this:
<myComp:FixedDataGrid >
<myComp:columns>
<mx:AdvancedDataGridColumn />
<mx:AdvancedDataGridColumn />
</myComp:columns>
</myComp:FixedDataGrid >
columns is a property on the AdvancedDataGrid, and therefore must be defined in the same namespace as your custom extension to the AdvancedDataGrid. AdvancedDataGridColumn is a different component, so it would be definined in the mx namespace.
As mentioned by an alternate poster, the 'myComp' namespace must be defined in the top level component of your application. Most of the time Flash Builder will add the namespace automatically for you.

Flash and Flex

I want to embed a Flash movie into Flex (Flex Builder 3), both using Action Script 3, and have my flash movie call functions in Flex and vice versa.
Is this possible?
Yes it is possible. If you want to embed another swf into your flex application you have a few options.
Option 1 - Embed the swf, inline, into a SWFLoader component. This option has some security drawbacks as the swf gets loaded into another application domain and so communication between your flex app and the embedded content can sometimes be difficult. You can give this component an id, listen to the complete event and then talk to the content property of SWFLoader to get access to the loaded swf. Something like:
<mx:Script>
<![CDATA[
private function completeHandler(event : FlexEvent) : void
{
trace(mySwfLoader.content);
}
]]>
</mx:Script>
<mx:SWFLoader id="mySwfLoader" source="#Embed(source='YourSwf.swf') complete='completeHandler(event)" />
Option 2 - You could use a meta tag to embed the swf as a class and then create an instance of that class in code. This is gives a lot of flexibility but you loose the benefits of being able to add the object declaratively. Something like:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="creationCompleteHandler(event)">
<mx:Script>
<![CDATA[
[Embed(source="mySourceSwf.swf")]
private var mySourceSwfClass : Class
private function creationCompleteHandler(event : FlexEvent) : void
{
var mySourceSwf = new mySourceSwfClass();
myCanvas.addChild(mySourceSwf);
trace(mySourceSwf);
}
]]>
</mx:Script>
<mx:Canvas id="myCanvas" />
</mx:Application>
Option 3 - Don't have a swf at all. Have whatever you want to embed as a UIMovieClip in the fla. You can then create a .swc file whenever you publish that fla. You can then link to that swc file in flex builder. this will then automatically add that MovieClip as referencable in your project (this may need some more investigation on your part). Essentially you can then do something like:
<local:MyMovieClipInSwc id="myMovieClip" />
This way you get the benefits of both worlds, declarative markup and everything within the same application domain. One thing i would say about this method is that Adobe royally f**ked up with the UIMovieClip class and it's performance sucks. Just be aware if you start to use this everywhere you app may become extremely sluggish.

How can I load images as icons dynamically into a TileList using flex?

Ok, so I have a custom render that I have created:
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"
horizontalAlign="center"
verticalAlign="middle"
width="100"
height="100">
<mx:Script>
<![CDATA[
[Bindable]
private var fileLabel:String;
[Bindable]
private var fileIcon:Class;
override public function set data(value:Object):void{
fileLabel = value.label;
fileIcon = value.file.url;
}
]]>
</mx:Script>
<mx:Image source="{fileIcon}" />
<mx:Label text="{fileLabel}" />
</mx:VBox>
That I want to use for a photo gallery with images that are dragged and dropped onto a TileList. I have that part down, but I can't seem to get the icon thing to work.
Given: value is sort of wrapper for a File class. I want to set the mx:Image source to something that needs to be of type Class. Using nativePath or url gives me a cast error. I see tons of examples online using XML and something like "Embed(/url/to/img.jpg)". I promise you that if you give me one of those examples (using a static image) I will give you a negative vote. THAT IS NOT WHAT IM LOOKING FOR HERE!
The reason that this isn't working is because the type of the fileIcon property is Class. You would generally would only want an object of type Class if you plan to use it like a factory, creating instances of that class with it. When you use the [Embed] metadata, you are indicating to the compiler that it should embed the specified asset into the SWF and also generate a Class to act as a factory for vending object instances that can represent that asset. However, as you had already discovered before posting this question, the problem with [Embed] is that you need to hard-code the reference, it doesn't let you supply a value at runtime (because the compiler needs to literally embed the asset, at compile-time).
Fortunately, mx:Image.source is a very flexible property that also accepts Strings (despite the fact that most documentation demonstrates using it with embedded assets). As long as the Flex application is capable of loading the asset, you can just supply a String-typed URL as the source.
Change the type of fileIcon to a String, and also verify that value.file.url is actually a URL of an image that your application can load. (You can test this just by hardcoding this URL into the mx:Image's source attribute.)

Resources