I red I can create "MXML components" and "AS3 components". The two methods use an existing component as their bases. The question: what if I can't extend any of the existing component (because I need something totally different)? Do I have to create the component from scratch using the (commercial) Flash authoring environment?
Apache – Flex custom components
apache-flexcomponents
Related Solutions
The easy thing to do is to swap the Application mxml tag with a VBox tag...thus making it act like a component.
e.g. If this were your application:
//Foo.mxml
<mx:Appliction xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Label text = "foo" />
</mx:Appliction>
change it to:
//Foo.mxml
<mx:VBox>
<mx:Label text = "foo" />
</mx:VBox>
and then you can do something like this:
//App.mxml
<mx:Appliction
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:local="your.package.scheme.*"
>
<local:Foo />
</mx:Appliction>
You may have to make some public properties if you need to pass in any data to the component...
That's one way of doing it, sure. But you could also create another class, say, to hold the data written by one (or any) of your components, then give each component a reference to that object; that might get you the same effect with a bit less code and manual event handling.
For example, the class object holding the data might look something like this (note the Bindable
attribute on the public member:
package
{
public class MyBindableObject
{
[Bindable]
public var myStringProperty:String = "";
public function MyBindableObject()
{
//
}
}
}
... and your main app container, which would instantiate the object initially (and hand out references to its subcomponents), like this:
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" xmlns:local="*" initialize="this_initialize(event)">
<mx:Script>
<![CDATA[
[Bindable]
private var myObject:MyBindableObject;
private function this_initialize(event:Event):void
{
myObject = new MyBindableObject();
}
]]>
</mx:Script>
<mx:TextInput text="{myObject.myStringProperty}" />
<local:MyCustomComponent myObject="{myObject}" />
<local:MyOtherCustomComponent myObject="{myObject}" />
</mx:WindowedApplication>
... and MyCustomComponent (note the Bindable
& Inspectable
attributes), which in this case happens to write to myObject.myStringProperty
directly:
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
[Bindable]
[Inspectable]
public var myObject:MyBindableObject;
private function myEventHandler(event:Event):void
{
myObject.myStringProperty = txt.text;
}
]]>
</mx:Script>
<mx:TextInput id="txt" text="{myObject.myStringProperty}" keyUp="myEventHandler(event)" />
... and MyOtherCustomComponent, which receives the changes made in the preceding component (and which are incidentally propagated to the container app as well):
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
[Bindable]
[Inspectable]
public var myObject:MyBindableObject;
]]>
</mx:Script>
<mx:TextInput text="{myObject.myStringProperty}" />
</mx:Canvas>
So again, the container app initializes the object instance, binds one of its own subcomponents' properties to the value of that object's property (optionally), and hands references to that object to whichever of its subcomponents might want to use it. The second component, in this case, writes the value, and the other two get the changes immediately, since the myStringProperty on the MyBindableObject class is marked Bindable, and each component contains a listener for changes to that property.
The example is somewhat simple in that it really just sets a string value on some object, thereby offloading the event-dispatching work to the Flex framework, which only eliminates a few lines of code -- but that's probably a good thing here, since there's really no need to design a custom event for simple text-change/property-change events, since Flex handles much or even all of that work for you.
Nevertheless it still depends on how much you're looking to customize your TextPanel. If you wanted to develop it into a more complex component, then I'd probably suggest moving the initial object instantiation into the TextPanel itself, do as you've done by defining and dispatching additional custom events, and having the main app and sibling component listen either for event notifications on the component or on the bindable object, either by textPanel.addEventListener (or similarly inline in MXML) or by textPanel.myObject.addEventListener, depending on which were appropriate.
Best Answer
You have the option of creating your own components. Enough documentation is available on Adobe's website. See:
*Custom Flex Components
*Custom Actionscript Components
You don't need Flex Builder 3 to create AS3/MXML based components. You can do that in any editor. What you do need is the SDK, which is free, for compiling these.