Does anyone know if it is possible to inject into a regular as3 (non mxml) class? I've tried with limited success.
Thanks
Could you be more specific? There's no difference between an "MXML" class and a class defined in ActionScript, it's just different ways of writing the same thing.
All that is needed for injection to work is a source property that is bindable and a destination property that is public (either a public setter or a public instance variable). If those two requirements are met and the code compiles it should work.
Look at the code for the example application you can find here: http://code.google.com/p/mate-examples/wiki/DocumentBasedExampleIntro and you will find a ton of injectors that target classes not defined using MXML (look for injectors targeting classes whose names end in "Model" especially). You can also find countless examples in the Mate forums.
Related
I am stuck in a doubt...
I have an aspx page that has to inherit 2 classes:
1) Class expand : Page, IPostBackEventHandler
2) mydll.classX
But I am unable to accomplish the same.
Any workaround that can be suggested would be really helpful...
Thanks
You can't inherit from more than one class in .NET. You should look into one of these methods to solve your problem:
Make your classX inherit Page. Now your new class can inherit classX, and it'll be a child class of both clasX and Page;
Use interfaces instead of classes. You're kinda doing that already, with IPostBackEventHandler. You can't inherit from multiple classes but you can implement as many interfaces as you want;
Use composition - that is, your class has a member that is of type classX. Read about object oriented design patterns, that may help you accomplish what you want in elegant ways that make things easier. See this question: What is composition as it relates to object oriented design?
Since you can't do multiple inheritance in what looks to be C# I think you will have to:
a. Replicate the public interface of myDll.classX and forward calls to an instance of myDll.classX
or
b. Make myDll.classX inherit Page, but that may not really be an option.
Without more information on what you are trying to accomplish, I can't really see any other options.
I have been using Flex / Flash Builder for a number of years. The latest release of Flash Builder (4.7) seems to come with quite a few problems, the biggest of those being:
Does not detect component IDs in MXML. For example, you cannot Find Usages of the ID of a component. Keeping the cursor on the ID of a component does not even mark occurrences of the ID. Instead, it marks occurrences of the actual id words in the MXML.
Extremely slow.
I am seriously evaluating moving over to IntelliJ IDEA 12, especially after reading many experienced Flex devs raving about it and recommending it.
I tried it. It took me a while to get to terms with the new terminologies of the IDE (made easy by this doc and very helpful support personnel at JetBrains).
I was able to setup my (large) projects in IDEA with Adobe Flex 4.6 SDK and got it to compile fine. But I noticed many "errors" highlighted in my AS files which are all actually false alarms.
The ActionScript editor doesn't seem to recognise the objects defined in MXML. Apparently, this is a known bug in IDEA (tracked here). And this bug has existed for more than 2 years!
Quoting the JetBrains support personnel:
I must admit that highlighting of ActionScript files which do not contain classes, but instead included in mxml as <fx:Script source="some_file.as"/> is probably the only weak part of IntelliJ IDEA code highlighting. False error highlighting will go away if you embed AS code inside CDATA of <fx:Script/> instead of referencing as external *.as file. Though I understand that this is not always desired.
I'm afraid the fix won't go into 12 release because the release is very soon and the fix is too risky. Priority of the issue depends on votes and user feedback. So far we have only 2 votes (http://youtrack.jetbrains.com/issue/IDEA-52598) and as the fix is pretty complex we still haven't implemented it thinking that this is a rare use case. I hope to fix it in one of 12.x update releases.
My project is a huge one, with huge MXML files and even more huge AS code for each MXML. So, for organisation purposes, I need to logically split them into smaller files. So, merging the AS code with the MXML is not practical. The false error highlighting just drastically reduces the readability of the code. Also, it does not allow Control / Command-clicking component IDs in AS code to quickly navigate to the definition of the component in MXML (which, incidentally, is now broken in FB 4.7 as well, but worked well in FB 4.6).
This bug in IDEA is unfortunately a deal-breaker for me. But I am wondering how other Flex devs are able to overcome / work around this seemingly critical bug.
It seems unbelievable to me that just 2 people have been affected by this bug, especially with so many Flex devs recommending IDEA. Maybe I am doing something wrong?
All you Flex developers, I would appreciate your thoughts.
UPDATE
This is in response to RIAStar's excellent and detailed answer. But it doesn't quite help me completely. Let me explain why and how I use <fx:Script source>. I am using Flex 4.x, with almost only Spark components.
Suppose a brand new Flex project. The main application is an MXML file.
In this MXML file, suppose I have a signup form.
On editing the form (in each field), suppose I have to run validations and enable the Submit button only if the form is completely valid. This would mean I need to assign change event handlers to the form items. The event handlers is AS code.
Suppose there is a username field which needs an on-type uniqueness check, by calling the server asynchronously. The server communication code is also AS code.
And then of course, there is the Submit button handler, which is also AS code.
I usually put all the AS code in separate .as files and include it in the MXML using <fx:Script source>. This AS code is usually quite heavy, with a lot of functional and behavioural logic. Many times, based on user action, even the components in the MXML and layout of the elements is modified through this AS code.
If I understand you guys right, none of this event handler code should be in these MXML script files. So, where should it be? How do you guys do it? I am not sure how the Spark Skinning architecture has anything to do with this.
Since I can't think of a gentle way of putting this, I'll just be blunt: I'm afraid the reason only two people think this is a critical bug, is that most seasoned Flex developers will agree that using <fx:Script source="some_file.as"/> is bad practice.
You effectively create two files that represent one class. From a readablity POV, which you seem concerned about, that's not a good move. One of these files (the .as file) is just a bunch of functions that cannot exist in their own right: they are tightly coupled to another file/class, but just looking at the .as file there is no way of knowing which class it is coupled to. Of course you can use some kind of naming convention to work around this, but in the end ActionScript/Flex is supposed te be used as a statically typed language, not a scripting language relying on mixins and naming conventions (don't get me wrong: I'm not saying scripting languages are bad practice; it's just not how ActionScript was conceived).
So what are your alternatives?
I suppose the main reason behind this construct is that you wish to separate MXML from ActionScript code, or in more abstract terms: separate the view from the logic. Fortunately this can be achieved in a few other, cleaner ways. Which solutions are available to you depends whether we're talking Flex 3 (or earlier) or Flex 4.
I realise that you may not have time to refactor your code to one of the proposed solutions, but I didn't want to leave you with just a "that's not good practice" answer.
Flex 3 (mx)
Code behind: A lot of developers used the so-called "code behind" pattern to separate their logic from their view. You can find plenty of information on the topic by Googling "flex code behind". I don't need to repeat all that in here. I'm not much of a fan of the concept because it relies heavily on inheritance and the two resulting classes are still pretty tightly coupled, but at least we're talking two classes. If you design your architecture well, you may even be able to reuse some of your base classes.
Compose model en controller: I used to create a separate "presentation model" class and a "controller" class for each MXML view and then use it something like this:
<!--MyView.mxml-->
<mx:VBox>
<m:MyModel id="model"/>
<c:MyController model="{model}" view="{this}"/>
...
</mx:VBox>
MVC purists won't like this, but it worked pretty well for me in thencontext of Flex applications.
Later when Direct Injection supporting frameworks (like Parsley) made their appearance, I could use injection to wire all those classes instead of hard-wiring them like in this example.
MVC frameworks: My knowledge of this topic is sparse (because in my opinion Flex is a very decent MVC framework that requires no third-party additions, but that's another disussion), but in short: they can help you separate logic from view in a clean way.
Flex 4 (Spark)
With Flex 4, the Spark skinning architecture was introduced, which allows for very nicely separated view and logic. You create a so-called 'host component' class in plain ActionScript, which contains all of the behavioural code, and a 'skin' class in MXML which defines the visual representation of the component. This makes designing reusable components very easy.
As per your request, here's a simplified example of how you might use Spark skinning to create your signup form.
Let's start with the skin class since it's easy to understand. It's just a form with some input fields. The HostComponent metadata tells the skin it's supposed to work together with the SignUp host component.
<!--SignUpSkin.mxml: the visual representation-->
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Metadata>
[HostComponent("net.riastar.view.SignUp")]
</fx:Metadata>
<s:Form>
<s:FormHeading label="Sign up"/>
<s:FormItem label="User name">
<s:TextInput id="userInput"/>
</s:FormItem>
<s:FormItem label="Password">
<s:TextInput id="passwordInput" displayAsPassword="true"/>
</s:FormItem>
<s:Button id="submitButton" label="Submit"
enabled="{hostComponent.canSave}"/>
</s:Form>
</s:Skin>
And now the host component in pure ActionScript. It has to extend SkinnableComponent to be able to use our skin (there's also SkinnableContainerwhich I've just recently explained in this question: Flex mxml custom component - how to add uicomponents?, but we won't be needing that here).
public class SignUp extends SkinnableComponent {
[SkinPart(required="true")]
public var userInput:SkinnableTextBase;
[SkinPart(required="true")]
public var passwordInput:SkinnableTextBase;
[SkinPart(required="true")]
public var submitButton:IEventDispatcher;
[Bindable]
public var canSave:Boolean;
override protected function partAdded(partName:String, instance:Object):void {
super.partAdded(partName, instance);
switch (instance) {
case userInput:
userInput.addEventListener(TextOperationEvent.CHANGE,
handleUserInputChange);
break;
case passwordInput:
passwordInput.addEventListener(TextOperationEvent.CHANGE,
handlePasswordInputChange);
break;
case submitButton:
submitButton.addEventListener(MouseEvent.CLICK,
handleSubmitButtonClick);
}
}
private function handleUserInputChange(event:TextOperationEvent):void {
validateUsername(userInput.text);
}
...
}
What's important here?
The variables marked as SkinPart will automatically be assigned the components with the same id that exist in the Skin you just created. For instance <s:TextInput id="userInput"/> will be injected into public var userInput:SkinnableTextBase;. Note that the type is different: SkinnableTextBase is the base class of TextInput; this allows us to create another skin with e.g. a TextArea instead of a TextInput and it'll work without touching the host component.
partAdded() is called whenever a SkinPart is added to the display list, so that's where we hook up our event listeners. In this example we're validating the username whenever its value changes.
When the validation is done, you can simply set the canSave property to true or false. The binding in the skin on this property will automatically update the Button's enabled property.
And to use both of these classes together:
<v:SignUp skinClass="net.riastar.skin.SignUpSkin"/>
I actually have become quite fond of using RobotLegs.
In my MXML views I try to keep all logic outside of the MXML and simply dispatch events out to the mediator. From there I can put code in the mediator to the heavier AS needed.
I want to extend or copy the PopUpManager class to add the ability to keep track of the number of windows.
I just want to add a simple windowCount++ when a window is added and windoCount-- when it's removed.
the problem is PopUpManager is a Singleton class... I wasn't able to make it work properly by extending it. And now I have tried to copy the code from the PopUpManager.as file and just add my variable to the end of its functions. It doesn't seem to be working though since it says my properties are undefined even though they are declared above the constructor.
I am thinking I would have to make a copy of the PopUpManagerImpl.as since that's wehre it seems much of the business resides (PopUpManagerImpl extends EventDispatcher implements IPopUpManager) would that allow me to have access to the variable? and should I ignore the manager and just put it in the implementation class?
here is a link about Using the Flex Singleton register, which helped me out when finding myself in the same situation.
I hope you can inspire from that too.
You likely didn't declare yours properties as static. The PopUpManager uses all static methods - this is why working with it you use syntax like:
PopUpManager.createPopUp(...
instead of
var popUpManager:PopUpManager = new PopUpManager();
popUpManager.createPopUp(...
This means that any variables declared in the PopUpManager need to also be static so as to be accessible at the class level.
public static var windowCount:int
I was wondering what happens to the code contained in an <mx:Script> tag. If I define a function tehre, it just becomes a member function of the generated class. But I noticed that it seems OK for the compiler if I just write some (static) method calls there (specifically, I call Font.registerFont()). It works fine, but I feel kind of guilty for doing this, because I have no idea what's really happening and when the code gets executed.
MXML is formally an ActionScript generation language. So, the Flex compiler will translate all MXML into ActionScript.
If you wan to see what happens; add the 'keep-generated-actionscript' argument to the compiler and then you can look at the generated ActionSCript code.
http://livedocs.adobe.com/flex/3/html/compilers_14.html#157203
Beyond that; I don't really understand your question. Why would static methods make you feel guilty?
Following the advice of www.Flextras.com's answer, I kept the generated Actionscript classes and had a look. The code inside <mx:Script> tags is simply put in the class body as-is. Knowing that, I could dig into the Flex livedocs and came across the following paragraph in the section about class definitions:
ActionScript 3.0 allows you to include not only definitions in a class body, but also statements. Statements that are inside a class body, but outside a method definition, are executed exactly once--when the class definition is first encountered and the associated class object is created.
So, putting statements inside a <Script> tag in an MXML file is equivalent to putting code in a static block in a Java class definition.
Is there a way to change private static field of an alien class?
For example:
package mx.managers {
public class TooltipManager ... {
private static var _impl:IToolTipManager2; // <- assign my own value here
...
}
}
In Java it is possible to do it using Reflection API. What about Flex?
No, that is not possible.
If you are looking into changing the implementation of the TooltipManager, have a look at the Singleton class in the Flex SDK. You'll need to create a custom implementation and register it via the Singleton class before the application initializes. The best is to override the application preloader and do the registration there.
Well, if you feel like you can handle the extra responsibility, you can monkey patch the class by copying the source into your own source tree with the same package and apply the necessary modifications. That way the flex compiler will use your implementation rather than the SDK implementation.
This technique is sometimes used as a last resort to fix issues which cannot be fixed otherwise. Drawbacks include issues such as forwards compatibility and unintended side effects in the same or other classes dependant on the class your editing.