This could potentially be a dumb question so apologies in advance if it is.
I'm wondering if theres an equivilant of Interfaces in MXML?
Everytime I feel the need to use an interface I always wind up making an actionscript and not an MXML file because I don't know if / how you can.
For example I was going to have a component based on vbox. I have 4 different implementions of the same thing so I decided to use an interface. But instead of making a single MXML interface and implementing it I've created an interface in as3. I've implemented this interface in 4 different classes.
I then have made 4 different vbox containers each with one of the different implementations in the script tag.
Does this sound like a reasonable approach or am I going against the grain here?
EDIT -- adding examples
The interface
package components.content.contents
{
public interface IContent
{
function init():void;
function doSearch():void
function setSearchTerm(term:String):void
}
}
Implementation (1 of 4)
package components.content.contents
{
public class ClipContent extends AbstractContent implements IContent
{
public function ClipContent()
{
}
public function init():void
{
}
public function doSearch():void
{
}
public function setSearchTerm(term:String):void
{
}
}
}
MXML File (1 of 4)
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300">
<mx:Script>
<![CDATA[
// ClipContent Container
import components.content.contents.ClipContent;
public var content:ClipContent= new ClipContent()
public function dostuff():void
{
content.init()
content.doSearch()
}
]]>
</mx:Script>
</mx:VBox>
You can use interfaces with MXML components this way:
// YourClass.mxml
<mx:HBox implements="IYourInterface">
is an MXML equivalent of
// YourClass.as
class YourClass extends HBox implements IYourInterface
But you still need to create the interface (in this example IYourInterface) in Actionscript.
MXML can implement an interface, like Robert Bak said, but it cannot define an interface.
No! MXML is a Declarative language for layout and positioning. By definition it needs an implementation. Interfaces are the definition of an API without an implementation.
It sounds like you're doing things exactly how I would. It is perfectly acceptable for an MXML Component to implement an interface. And it is perfectly acceptable to have multiple components implement the same interface to achieve different results.
For the sake of completeness, an MXML Component can implement an interface just like an ActionScript component ca:
<mx:myComp implements="com.myClass.Interface">
You are correct, there is no way to implement a true interface using MXML(edit: I stand corrected, you can use the "implements" keyword as described in the other answers.) Another approach to consider is to use a "code behind" actionscript file for each of your 4 MXML files:
MXML file (MyFancyVBox.mxml):
<?xml version="1.0" encoding="utf-8"?>
<MyFancyVBoxCode>
...
</MyFancyVBoxCode>
AS file (MyFancyVBoxCode.as):
package com.something.whatever
{
import com.something.another.IFancyInterface;
public class MyFancyVBoxCode implements IFancyInterface
{
...
}
}
The downside is that it doubles the number of source files.
Firstly, I agree with Wade that Code behind may help you.
Secondly, I am thinking do you need the interface in you case. In your question, you want "4 different implementions of the same thing". How about using the "state" in the mxml. It may solve you problems.
Related
I find the flexibility in using fx:script to get all AS3 see each other easily but I have a few MXML module, some actionscript from main.mxml want to access the ID in specific module such as module1.mxml. How do I get it to work?
Assuming you have a module1.mxml is a defined component in main.mxml, you can give it an ID and reference public variables and functions inside of it. The following shorthand code demonstrates this.
<mx:Application creationComplete="creationCompleteHandler()">
<fx:Script>
function creationCompleteHandler() : void
{
m1.initializeModule();
}
</fx:Script>
<module1 id="m1" />
</mx:Application>
im writting an actionScript class to handle my web service calls. When i retrieve a result i want to call a setter method in my main mxml application. My problem is that i dont know how to access the methods in the actionScript section of my main mxml class from my actionscript class, any ideas?
David is right -- while you can access the public members of your Application.mxml object statically and from anywhere in your application, design-wise that's a bit of a no-no. It's better to strive for loose coupling between your objects, and the way that's done in the Flex idiom is generally to extend EventDispatcher and to dispatch events. So for example, your WebService wrapper might look something like this:
public class MyWrapperClass extends EventDispatcher
{
[Event(name="webserviceComplete", type="flash.events.Event")]
public function MyWrapperClass(target:IEventDispatcher=null)
{
super(target);
}
private function handleWebServiceLoadComplete(event:ResultEvent):void
{
dispatchEvent(new Event("webserviceComplete"));
}
public function doWork():void
{
// Load the service, etc., and ultimately call handleWebServiceLoadComplete()...
}
}
... and your Main.mxml file like this:
<mx:Script>
<![CDATA[
private function app_creationComplete(event:Event):void
{
var myWrapper:MyWrapperClass = new MyWrapperClass();
myWrapper.addEventListener("webserviceComplete", mywrapper_webServiceComplete, false, 0, true);
myWrapper.doWork();
}
private function mywrapper_webServiceComplete(event:Event):void
{
// Do the work you would've otherwise done in the public method
}
]]>
</mx:Script>
In this case, the end result is the same -- completing the web-service load triggers the function in Main.mxml. But notice how mywrapper_webServiceComplete() is declared privately -- it's not called directly by MyWrapperClass. Main.mxml simply subscribes (with addEventListener()) to be notified when MyWrapperClass is finished doing its work, and then does its own work; MyWrapperClass knows nothing about the details of Main.mxml's implementation, nor does Main.mxml know anything about MyWrapperClass other than that it dispatches a webserviceComplete event, and exposes a public doWork() method. Loose coupling and information hiding in action.
Good luck!
If your class is an UIComponent added to the component tree, then you can use its parentApplication attribute. Otherwise, use the static Application.application attribute, but only after the application initialization has completed. Earlier than that, the field is null. Private fields and methods obviously cannot be accessed. Elements declared in the MXML part with explicit ids are public.
Adding such a call creates a rigid binding, though. You might want to consider dispatching an event instead, and handling this event in the main application.
In case anyone has the same problem:
mx.core.FlexGlobals.topLevelApplication.YOUR_FUNCTION
is the syntax to access public functions within the main.mxml.
I have a MXML with a form, and inside it, two TextInputs. I hate having any piece of code inside the MXML file (I come from a JavaScript formation) so I use a
mx:Script source="external.as"
tag to include any code used in any MXML file. The problem is that if I have this code on the external.as file:
private function populateFromForm():void{
var vo:ValidObject= new ValidObject();
vo.market = marketInput.text;
vo.segment = segmentInput.text;
vo.priceLow = priceLowInput.text;
vo.priceHigh = priceHighInput.text;
}
Where marketInput, segmentInput, priceLowInput and priceHighInput are TextInputs defined in the MXML file. When I try to complile I get a 1120: Access to undefined property XXXXX
I have tried adding this lines prior to the function:
public var marketInput:TextInput;
public var segmentInput:TextInput;
public var priceLowInput:TextInput;
public var priceHighInput:TextInput;
But instead I get a 1151:A conflict exists with definition XXXX in namespace internal which makes perfect sense.
Is there a way to do this without having to pass all the input references to the function as parameters of it?
You need to create a reference to an instance of the TextInputs' parent container, and then use that reference to accsess the TextInputs and their properties. I think we need some clarification on your file structure. How are you creating the instance of the parent container? I'm thinking this is what you need to do:
MyForm.mxml:
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:TextInput id="marketInput" />
<mx:TextInput id="segmentInput" />
<mx:TextInput id="priceLowInput" />
<mx:TextInput id="priceHighInput" />
</mx:VBox>
SaveVOContainer.as:
package
{
public class SaveVoContainer extends Container
{
private var myForm:MyForm = new MyForm();
public function SaveVOContainer
{
this.addChild(myForm);
}
private function populateFromForm():void{
var vo:ValidObject= new ValidObject();
vo.market = myForm.marketInput.text;
vo.segment = myForm.segmentInput.text;
vo.priceLow = myForm.priceLowInput.text;
vo.priceHigh = myForm.priceHighInput.text;
}
}
}
Doing a "code-behind" is painful in Flex. There is no concept of partial classes or the flexibility of prototypal inheritance as in Javascript. Google for "code-behind in flex" for many resources.
I think it's better you get used to the idea of embedding code in mxml. Use script tags avoiding inline code as much as possible. If you have to write a lot of code within MXML, perhaps you may want to re-factor the code into multiple custom components. Bonus points if they are reusable.
The canonical way to do code-behind in Flex is via inheritance. Here's a good explanation from the docs: http://learn.adobe.com/wiki/display/Flex/Code+Behind. In a nutshell:
Declare an ActionScript class to use as your base class.
Set the base class as the root container in your MXML file.
For any controls declared in your MXML file, you have to redeclare them as public members of the base class using the exact same name (exactly as you are doing above for your script block with source tag, only it works :-)
So, your ActionScript file:
package mypackage
{
import mx.controls.TextInput;
public class myClass extends WindowedApplication
{
public var marketInput:TextInput;
private function populateFromForm():void{
/* As above */
}
}
}
And the corresponding MXML file:
<?xml version="1.0" encoding="utf-8"?>
<custom:myClass xmlns:custom="mypackage.*"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<mx:TextInput id="marketInput"/>
</custom:myClass>
Et cetera for your other TextInput controls. And now your populateFromForm function should work.
It is kind of heinous to have to redeclare the same entities twice, but it's not quite the bag of hurt the earlier respondent made it out to be (although it's possible this changed in Flex 4 to make it less painful than it was).
import this in .AS:
import mx.core.Application;
in the .AS use this:
mx.core.Application.application.component.property = value;
mx.core.Application.application.myText.text = 'test';
do you have a script tag in your mxml file that points to your ActionScript file?
<mx:Script source='includes/foo.as' />
I'm currently maintaining some flex code and noticed very many functions which are declared like:
private function exampleFunc():void {
....
}
These functions are in the global scope, and aren't part of any specific class, so it's a bit unclear to me what effect declaring them as private would have. What restrictions does the "private" qualifier have for functions like this?
The actionscript functions that are included in your mxmlc code will we available as a part of your mxmlc component, which behind the scenes is compiled into a class. Therefore marking them as private makes them inaccessible.
Here is an example to make that clear, say you have the following component, we'll call it FooBox:
<!-- FooBox.mxml -->
<mx:Box xmlns:mx="http://www.macromedia.com/2003/mxml">
<mx:Script><![CDATA[
private function foo():void {
lbl.text = "foo";
}
public function bar():void {
lbl.text = "bar";
}
]]></mx:Sctipt>
<mx:Label id="lbl">
</mx:Box>
I can now add FooBox to my application, and use it's functions:
<mx:Application
xmlns:mx="http://www.macromedia.com/2003/mxml"
xmlns:cc="controls.*"
>
<mx:Script><![CDATA[
private function init():void {
fbox.foo(); // opps, this function is unaccessible.
fbox.bar(); // this is ok...
}
]]></mx:Sctipt>
<cc:FooBox id="fbox" />
</mx:Application>
If the actionscript functions are included in your Main Application file, the I think you can call the functions from an child control through the Application.application object, something like:
Application.application.bar();
if the bar function was placed in the main mxmlc code.
What do you mean by global scope? Are these functions declared in the main MXML file?
In general, private means that functions can only be called from within the class that declares them.
But, when you put it in a actionscript file .as is it still compliled into a class ?
Because asdoc doesn't like it.
I'm having trouble with getting icons from resource bundle in Flex. Here's the scenario:
Directory structure looks like this:
-ResourceManagerTest
-resources
-icons
-icon1.png
-icon2.png
-icons.properties
-src
-MyButton.as
-ResourceManagerTest.mxml
In icons.properties I have:
CIRCLE_FILLED=Embed("icon1.png")
CIRCLE_CONTOUR=Embed("icon2.png")
I'd like to create ToggleButtonBar with buttons whose icons are pulled out from resource bundle.
Here's the source of programmatically created button:
package
{
import mx.resources.ResourceManager;
public class MyButton extends Object
{
public var icon:Class;
public function MyButton()
{
super();
icon = ResourceManager.getInstance().getClass("icons", "CIRCLE_FILLED");
}
}
}
And here is ResourceManagerTest where I define the ToggleButtonBar:
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
creationComplete="onCreationComplete()">
<mx:Script>
<![CDATA[
[Bindable]
public var dataProvider:Array;
public function onCreationComplete():void {
dataProvider = new Array();
dataProvider.push(new MyButton());
dataProvider.push(new MyButton());
tgb.dataProvider = dataProvider;
}
]]>
</mx:Script>
<mx:ToggleButtonBar id="tgb"/>
Buttons do appear, however without any icons. What am I doing wrong?
Firstly it looks like you are not including the resource bundle in your build. You're probably going to need something like
<mx:Metadata>
[ResourceBundle("RegistrationForm")]
</mx:Metadata>
in the MXML or just
[ResourceBundle("RegistrationForm")]
at the top of your class
Once you've done that make sure you have the bundle... try adding just a string resource and see if you can get that. If you have the bundle and it still doesn't work have a play with different paths for you icons. They may not be relative to the resource (with out playing with it i can never remember what is relative to what).
The best resource I've found for information about how to setup ResourceBundle in Flex 3 is "Using Resources" in Adobe's livedocs.
[ResourceBundle("icons")]
In addition to including the resource bundle, you need to make sure you include the resource path at compile time. Read Adobe's docs for more information.