Thursday, July 26, 2012

Custom Component in Flex (Part One)

Finally here is the long waited post. This post will have many parts as this topic can not be covered in one post. So first question is What is Custom Component? In very simple terms a custom component is a component which is customized (changed in someway) to suit our requirements. It may be a brand new components or may be an extension of existing component.
Now there can be various scenarios when we need custom components. We need custom components for many reasons, some of them are:
1. The existing standard component does not provide the functionality we need. Some examples can be: we want a prompt text in a textinput that will help user in inserting proper text inside it (promptText property is now available for Spark TextInput but it was not there previously). Another example can be where we want some very small visual change for the component (Round corner button with label Submit say). This can lead to change in skin if we use spark component or overriding updateDisplayList for UIComponent.
2. Another reason may be we need a component and no existing component can serve the purpose. In one of my project I need a highly flexible Locomotive component. I had to start from the scratch using graphics and all.
3. Another reason may be we have some particular set of lines in our MXML code and that is needed everywhere. For example we have a combo box that is containing the list of countries/states and we want that combo box at multiple places in our application. One option is to copy the code everywhere. The problem will appear when we need to make frequent changes to that combobox (may be adding new countries/states based on some conditions). A better option is to create a MXML or ActionScript component based on combobox and provide all the values inside it and then use it everywhere. Creating it in MXML will be easy but it would be more efficient in ActionScript. Actually when we need lot of customization and also have concern for code performance then we prefer ActionScript. For very minor changes going with MXML is also fine, as doing the same in ActionScript may be over engineering some times. Check the following example taken from Adobe website:


 <?xml version="1.0"?> 

 <!-- createcomps_intro\StateComboBox.mxml --> 

 <!-- Specify the root tag and namespace. --> 

 <s:ComboBox xmlns:fx="http://ns.adobe.com/mxml/2009"  



   xmlns:s="library://ns.adobe.com/flex/spark"  

   xmlns:mx="library://ns.adobe.com/flex/mx"> 

   <s:dataProvider>   

     <s:ArrayList> 

       <fx:String>AP</fx:String> 

       <fx:String>UP</fx:String> 

       <fx:String>MP</fx:String> 

       <!-- Add all other states. --> 

     </s:ArrayList> 

   </s:dataProvider> 

 </s:ComboBox>  


Now we can use it anywhere like:


 <?xml version="1.0"?> 

 <!-- createcomps_intro/IntroMyApplication.mxml --> 

 <!-- Include the namespace definition for your custom components. --> 

 <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"  

   xmlns:s="library://ns.adobe.com/flex/spark"  

   xmlns:mx="library://ns.adobe.com/flex/mx" 

   xmlns:MyComp="*"> 

   <!-- Use the filename as the MXML tag name. --> 

   <MyComp:StateComboBox/> 

 </s:Application>  



So these are some of the reasons. I have already given one very simple example of custom component above. We can also create very simple custom component in ActionScript as well. Lets create a button with label 'Submit'. This can also be done in MXML but it can also be done in ActionScript easily. How to write a custom component and how to decide between MXML and ActionScript comes with practice.


 package myComponents 

 { 

   // createcomps_intro/myComponents/MyButton.as 

   import spark.components.Button; 

   public class MyButton extends Button { 

     // Define the constructor.  

     public function MyButton() { 

       // Call the constructor in the superclass.  

       super(); 

       // Set the label property to "Submit". 

       label="Submit"; 

     } 

   } 

 }  


This can be used as:


 <?xml version="1.0"?> 

 <!-- createcomps_intro/MyApplicationASComponent.mxml --> 

 <!-- Include the namespace definition for your custom components. --> 

 <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"  

   xmlns:s="library://ns.adobe.com/flex/spark"  

   xmlns:mx="library://ns.adobe.com/flex/mx"  

   xmlns:MyComp="myComponents.*"> 

   <!-- Use the filename as the MXML tag name. --> 

   <MyComp:MyButton/> 

 </s:Application>  



One golden rule I have found is: Always do your analysis first to check whether an existing component can be extended to satisfy your needs. Never give first preference to start from scratch. This is a very simple post and hopefully there has not been any problem till now. The next posts will cover this topic in more detail. Meanwhile try to create a custom Textinput component which has the functionality of clearing the text the moment user clicks inside it. Try using ActionScript.
Hint: We will start with extending Spark Textinput and we will add a mouse click event listener to it in the constructor, just after super call. Then in the corresponding event listener we will set the  text property of this custom component to empty String. Then try to use it at various places and see if it works.

Some good links are (just skim through them):
http://www.ibm.com/developerworks/web/library/wa-flexrendering/
http://help.adobe.com/en_US/flex/using/WS2db454920e96a9e51e63e3d11c0bf684f9-7fff.html

Let me know your feedback and things you would like to be covered.

No comments: