Let's say I have an interface
public interface IFoo {
...
}
and I have several implementing classes
public class Foo implements IFoo {
...
}
...
public class Bar implements IFoo {
...
}
...
public class Baz implements IFoo {
...
}
I want to reference IFoo in MXML like this
<ns:IFoo id="myfoo"/>
and have it be instantiated at runtime by a factory.
However, the compiler won't let me do this-- it's trying to do "new IFoo" in the generated ActionScript.
How to get around this? How can I use an interface and a factory purely in MXML?
Declaring an MXML child instantiates an object of that type - you can't simply declare a property in MXML without associating an instance with it.
Given that - there's no way to achieve the equivalent of
public var myFoo:IFoo;
in your MXML.
As James pointed out, you can use a ClassFactory to acheive the following:
<mx:ClassFactory class="{Foo}" id="fooFactory" />
but you would be required to call fooFactory.newInstance() to get an IFoo.
You can implement interfaces in MXML components with the implements="IFoo" attribute in the component's root node.
Edit:
Sorry, I missunderstood your question. I don't know a way to implement a factory in pure mxml. I guess you have to use Actionscript or mxml states to achieve a similar behaviour.
Check out ClassFactory. It is how things like item renderers are instantiated.
Related
I'm using Flex 4.5, and I have imported a custom class I wrote into the main MXML file.
Inside the class file, I want to be able to create a TitleWindow using the PopUpManager like this:
package classes {
import components.*; // My custom components
import mx.managers.PopUpManager;
public class SomeClass {
public function showPopUp():void {
PopUpManager.createPopUp(this,NewProjectPrompt,true);
}
}
}
NewProjectPrompt is a custom component I made. The compiler is giving me the following error:
1067: Implicit coercion of a value of type classes:Project to an unrelated type flash.display:DisplayObject.
This is because this isn't pointing at WindowedApplication. How do I make the first parameter in .createPopUp() point to the WindowedApplication?
this code works!
public function showPopUp(){
PopUpManager.createPopUp(FlexGlobals.topLevelApplication as DisplayObject,NewProjectPrompt,true);
}
If your WindowedApplication file is named "MyApp.mxml" then you would write a reference from a component to it like this:
MyApp(this.parentApplication)
This will return the actual WindowedApplication and you can call its public methods or stick it in a variable if need be.
how can i do binding exists property in actionscript e.g. i want image still in middle aplication..in mxml i do this simple as <mx:Image source="image.jpg" x="{this.width/2}"/> ...i don't know how can i do this simple in actionscript without event handlers... i put this code to application_creationCompleteHandler..
something like var image:Image = new Image(); image.source="image.jpg"; image.x=this.width/2; or have i put this to another function?? i can't do e.g. updateComplete event handler and change it there...
thanks
pavel
Check the BindingUtils class and its bindSetter method. You can bind a setter to the "width" property and adjust the x property of your image in that handler.
Considering that as3 is OO language i always start from something like this:
public class App extends Sprite {
public function App() { //constructor
super(); //extends class constructor
loading(); //your function were you set all elements properties
}
}
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.
I've embedded a MovieClip symbol with the [Embed] syntax into my AS3 project, which I'm compiling with the Flex 3 SDK. That MovieClip has instances of other clips within it that are placed on stage with instance names. I can't just access them by instance name like I would if I were compiling with the Flash IDE.
How can I reference them?
you need to both give them instance names in the IDE and declare them in the class you've embedded them on.
So say that you have instances of baz and frr on your embedded class InfoPopup, you need to declare them like this:
package foo {
import flash.display.Sprite;
[Embed(source='../../../../../../assets/Assets.swf', symbol='InfoPopup')]
public class InfoPopup extends Sprite {
public var baz:Sprite;
public var baz:MovieClip;
public function InfoPopup(){
trace("constructor!");
}
}
}
When added like this they have to be public properties or else the compiler will complain.
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.