For Flex Beginners - Exposing Properties and Events When Creating A Custom Component In Flex
http://www.brucephillips.name/blog/index.cfm/2007/4/22/For-Flex-Beginners--Exposing-Properties-and-Events-When-Creating-A-Custom-Component-In-Flex
When creating a custom component in Flex, you may want to include the ability for other components or the main application to provide information to the custom component and to be notified when the custom component dispatches events. You want to make your custom component as flexible as possible so that it can be used in a variety of applications.
Recently, I created a custom component based on the mx:Form component. I included the ability for anyone using this component to provide the information that would populate the form fields. The custom component also generates its own event when the submit button is clicked. Thus, the main application that uses this custom form component can register for this event and provide its own event handler.
You can see a very simple demo application of a custom form component prototype that includes these capabilities here (right click the application to view the source). After the application starts, make any changes to the values in the form fields and then click on the submit button.
First I have a Person ActionScript class. Note that this Person class is Bindable and includes public set and get methods. As the code below shows, my custom mx:Form component uses an object of class Person to populate its form fields with values.
<mx:Form xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300" >
<!---create a custom event that this custom component can generate
see pages 109-112 in Creating and Extending Flex 2 Components
The Metadata tags will ensure that this event shows up in code hinting-->
<mx:Metadata>
[Event(name="formSubmitted", type="flash.events.Event")]
</mx:Metadata>
<mx:Script>
<![CDATA[
import people.Person;
import mx.controls.Alert;
[Bindable]
private var _person:Person ;
//public function to get and set //_person Object
public function get person():Person {
return _person;
}
public function set person(person:Person):void {
_person = person;
}
/*Called when user clicks on the Submit button
*/
public function submitForm():void {
//update _person Object with current //values in the form _person.firstName = firstName.text;
_person.lastName = lastName.text ;
_person.email = email.text
// Define event object, initialize it, then dispatch it. dispatchEvent( new Event("formSubmitted") );
} //end function submitForm
]]>
</mx:Script>
<mx:FormItem label="First Name:">
<mx:TextInput
id="firstName"
text="{_person.firstName}"
/>
</mx:FormItem>
<mx:FormItem label="Last Name:">
<mx:TextInput
id="lastName"
text="{_person.lastName}"
/>
</mx:FormItem>
<mx:FormItem label="Email:">
<mx:TextInput
id="email"
text="{_person.email}"
/>
</mx:FormItem>
<mx:ControlBar horizontalAlign="center">
<mx:Button
id="submitButton"
label="Submit"
click="submitForm()"
/>
</mx:ControlBar>
</mx:Form>
To provide a Person object to the custom Form component I use the following code in the main application:
<![CDATA[
import people.Person;
import mx.controls.Alert;
[Bindable]
private var aPerson:Person ;
/*called automatically when this app
is finished being created
*/
private function createPerson():void {
aPerson = new Person("Bruce", "Phillips", "Bruce@Phillips.name");
//Alert.show( aPerson.toString() );
}//end function creatPerson
/*
Called automatically when the PersonForm component
dispatches the formSubmitted event
*/
private function handleFormSubmitted(eventObj:Event):void {
//get the Person object //from the PersonForm
aPerson = personForm.person ;
Alert.show("Person back from PersonForm component: " + aPerson.toString() );
}//end function handleLoginSuccess
]]>
</mx:Script>
<!--use PersonForm component bind person property to aPerson
object and specify a function
to call in response to the formSubmitted event-->
<myComp:PersonForm id="personForm" person="{aPerson}" formSubmitted="handleFormSubmitted(event)" />
In this demonstration of the concept, when the main application is finished being created, the createPerson function is executed. In that function a Person object is created (named aPerson). When I add the PersonForm component to the main application, I specify that the PersonForm's person property is bound to the aPerson Object.
Therefore the PersonForm's fields will have the values of the aPerson's firstName, lastName, and email.
If you examine the PersonForm's code you'll see that I created a new event named formSubmitted. When the user clicks on the submit button in PersonForm (see function submitForm), I update the values of the PersonForm's person object with the values from the form fields and then dispatch the formSubmitted event.
In my main application I specified that the formSubmitted event generated by the PersonForm component will be handled by the handleFormSubmitted function. In that function I reassign my main applications Person object (aPerson) to the Person object that is a property of the PersonForm component. Now my main application's Person object has the same firstName, lastName, and email as the PersonForm component's Person object. So if any changes were made before the user clicked on the submit button in the PersonForm component, my main application's Person object now has those changes.
(Note: Because the Person object in the PersonForm component is set to equal the main application's Person object the code aPerson = personForm.person in function handleFormSubmitted is not really necessary. Any changes made to personForm.person are also made to aPerson since the two objects were assigned to each other.)
By providing public set and get Person properties and a new event in my PersonForm component I've provided users of the PersonForm component the ability to provide information to the PersonForm and to get information out of the PersonForm. The event I added is one the user can register for and then respond to that event and get the Person object that was changed back out of the PersonForm component.
