Saturday, May 1, 2010

Flex 4: Adding States and changing properties,styles and events for states

Flash Builder 4 has improved a lot for developer and designer. It has ease out the syntax for working with states; now working with States is much easier and faster compare to Flex 3. In Flex 3, most of us used the design mode for working with states, I personally believed that writing code for states in Flex 3 was much more tedious and time consuming, and hence I had always used the Design mode.

Now with the new release for Flex, Many things has improved for developers and designer.

In this tutorial, I will walk you through the steps to use the code for working with states using Flash Builder 4. I will also explain how we can change the property and handle the events for two different states.

We will create the simple example which will have two states; each state will have common components, Label and Button. Both components will have different values depending upon the current state.

To start with first we will create the Flex project using Flash Builder 4. Once you are done open the application.mxml file.

In this tutorial, we will have Lable stating the current state string and one button to change the states. To add this add following code just after the Application tag.
<s:layout>
<s:VerticalLayout horizontalAlign="center" paddingTop="20"/>
</s:layout>
<s:Label text="We are at state 1" width="100%" textAlign="center"/>
<s:Button label="Go To State 2"/>
In above code snippet, we have set the VerticalLayout layout using <s:layout> tag. The syntax for setting Layout is also changed in Flex 4. Just after that, we have set the Label and Button spark component. Label has the value for current state information and button has label for moving to next state.

We are done with creating default state, Now As mention earlier we will create two different states in this application. To do this we need to add following code just after the Application starting tag.

<s:states>
<s:State name="State1"/>
<s:State name="State2"/>
</s:states> In the above code snippet, we have declared the two states using <s:states> tag. It is very simple, add as many child tag of <s:State>
within States tag. Add the name property for each state. For this tutorial we have mentioned State1 and State2.

We are done with declaring two different states, but we need to change the properties and event handler for buttons for two different states. In Flex 4, we can change the properties of component for different states using (.) syntax followed by the state name attribute as shown here <B>style.stateName</B> The properties, styles and events are declared without (.) and state name, will be considered for default state. We have created Label and button earlier, in which we haven’t mention the (.) and state name, Hence that will be considered for the default state.

Now as we have initialize two different state, we have to change the values of Label and Button for different states. To change the values for State2, we will add the properties with (.) syntax followed by the state name. Update your <s:Label> and <s:Button> button tag as follow.
<s:Label text="We are at state 1" width="100%" textAlign="center" text.State2="We are at state 2"/>
<s:Button label="Go To State 2" label.State2="Go To State 1" click="currentState = 'State2'" click.State2="currentState = 'State1'"/>
You can see that we have change the text property of Label tag for State2 to <B>text.State2="We are at state 2"</B> Same way we have some event to navigate through the states. To do so, we have added an event for <s:Button>tag for both the states as <B>click="currentState = 'State2'" click.State2="currentState = 'State1'"</B>. If you see above the syntax for changing the state is <B>currentState = 'State Name'</B>.

Now we are done with our application. The final code for your application will look like this.
<?xml version="1.0" encoding="utf-8"?>
<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" minWidth="955" minHeight="600">

<s:states>
<s:State name="State1"/>
<s:State name="State2"/>
</s:states>

<s:layout>
<s:VerticalLayout horizontalAlign="center" paddingTop="20"/>
</s:layout>
<s:Label text="We are at state 1" width="100%" textAlign="center" text.State2="We are at state 2"/>
<s:Button label="Go To State 2" label.State2="Go To State 1" click="currentState = 'State2'" click.State2="currentState = 'State1'"/>

</s:Application>
You are done, Just run your application and find the output.

It is very simple and easy to work with states in Flex 4. I hope you like this tutorial.

I will write another tutorial for states, in which I will include how we can add / remove components for states.

Read more...

Friday, April 30, 2010

Flex 3: RTE Bullet and Align button issue

While working with Rich Text Editor component of Flex 3, I cam across with strange issue.

Try out following flow. On fresh launch change Font / Font Size / Font Color / Bold / Italic / Underline and then if you click on either alignment buttons or Bullet button. Ideally all formatting setting should retain and whatever you type should have these formatting. But it is failing. The formatting will revert back to the default values.

I tried to find out the actual issue, In the RichTextEditor.mxml, within the setTextStyles function. New text format instance is been created in Bullet and align button click condition. This new TextFormat object overwrites the previously set formatting.

else if (type == "align" || type == "bullet")
{
if (beginIndex == endIndex)
{
tf = new TextFormat();
}

To overcome this issue I have written a fix in the mxml where RTE instance is been created. To fix this issue, I just had assigned the formatted values to the newly created TextFormat object, Doing this will retain the previously set formatting.
Following is the code snippet for the fix.

public function checkForFormating():void
{
var textField:IUITextField = textArea.getTextField();
var beginIndex:int = textField.selectionBeginIndex;
var endIndex:int = textField.selectionEndIndex;
if (beginIndex == endIndex)
{
var tf:TextFormat;
tf = textField.defaultTextFormat;

tf['font'] = fontFamilyCombo.text;

var fontSize:uint = uint(fontSizeCombo.text);
if (fontSize > 0)
tf['size'] = fontSize;

tf['color'] = uint(colorPicker.selectedColor);

tf['bold'] = boldButton.selected;
tf['italic'] = italicButton.selected;
tf['underline'] = undoButton.selected;

if (alignButtons.selectedIndex == 0)
tf.align = "left"
else if (alignButtons.selectedIndex == 1)
tf.align = "center"
else if (alignButtons.selectedIndex == 2)
tf.align = "right"
else if (alignButtons.selectedIndex == 3)
tf.align = "justify"

tf['bullet'] = bulletButton.selected;

if (lineSpaceButton.selectedIndex == 0)
tf.leading = "2"
else if (lineSpaceButton.selectedIndex == 1)
tf.leading = "4"
else if (lineSpaceButton.selectedIndex == 2)
tf.leading = "8"

textField.defaultTextFormat = tf;
}
}
In this function, basically i have reassign all the formatting based on the default formatting property. All you have to do is call this function on bullet / align button click. Add a Mouse Click listener and call this function on handler.

This will resolve the issue. I have tested this and it works fine, Let me know if you find any issue in this.

Read more...

Wednesday, April 28, 2010

Flex 3: Cross Domain XML Loading

Flash Player has security feature, This security is basically domain based. It will allow a swf from specific domain to load assets, data or it will allow communication between two swf files from that domain. When a particular swf file is loaded in flash player, Security sandbox is created for that particular domain. This mean swf file in that domain will have access to all assets, data of that sandbox.

If a swf file from any particular domain wants a access to data or assets of any other domain, we need to have cross-domain policy file available on remote server. This crossdomain.xml needs to be structure in predefined format, Which will be read by the swf player and depending upon the tags, it will allow access to that server.

Following is the sample code for crossdomain.xml.

<?xml version="1.0"?>
<cross-domain-policy>
<!-- below tag will allow access from any domain. -->
<allow-access-from domain="*"/>
<!-- below tag will allow access to www.shaileshmak.000fees.net domain. -->
<allow-access-from domain="www.shaileshmak.000fees.net"/>
<!-- below tag will allow access to any sub domain of 000fees.net domain. -->
<allow-access-from domain="*.000fees.net"/>
<!-- below tag will allow access to 105.216.0.40 ip. -->
<allow-access-from domain="105.216.0.40"/>
</cross-domain-policy>
If a swf tries to access any data from other domain, swf player by default search for the crossdomain.xml file at root directory of the remote server. If the crossdomain.xml is placed other than the root directory, We can access that file using Security.loadPolicyFile(); function.

e.g.
Security.loadPolicyFile(http://www.shaileshmak.000fees.net/MyWork/crossdomain.xml);
Make sure you are loading this crossdomain.xml file, before loading the assets from the remote server.

I have created a Flex example for loading xml into the datagrid, In this example, the data xml file is located at remote server and the swf file from different server is accessing this xml and loading it into the datagrid.

Following is the sample code of the application.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
creationComplete="init()">

<mx:HTTPService id="service"
showBusyCursor="true"
url="http://shailesh.ihemant.com/employee.xml"
resultFormat="object"
result="serviceResultHandler(event)"
fault="serviceFaultHandler(event)"/>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.controls.Alert;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;

[Bindable]
private var employeeCollection:ArrayCollection;
private function init():void
{
employeeCollection = new ArrayCollection();
}

private function serviceResultHandler(event:ResultEvent):void
{
employeeCollection = event.result.Employee_Info.Employee as ArrayCollection;
}

private function serviceFaultHandler(event:FaultEvent):void
{
Alert.show(event.toString());
}

private function getEmployeeHandler():void
{
service.send();
}
]]>
</mx:Script>

<mx:Button id="getEmployee"
label="Get Employee"
click="getEmployeeHandler();"/>

<mx:DataGrid id="grid"
width="80%"
dataProvider="{employeeCollection}">
<mx:columns>
<mx:DataGridColumn dataField="Name" headerText="Name"/>
<mx:DataGridColumn dataField="Designation" headerText="Designation"/>
<mx:DataGridColumn dataField="Email" headerText="Email"/>
</mx:columns>
</mx:DataGrid>
</mx:Application>
Look at the demo application.

Read more...

Sunday, April 25, 2010

Flex 4: New components and containers

With the introduction to new Flash Builder 4 (Flex 4 - code base Gumbao), There are changes in the component architecture. Flex 4 SDK introduce number of new components and container with new architecture. This will make developers life much easier, as the skinning, effects and other customization now will be much straight forward. In Flex 4 new component they have introduced Spark Components.

Following table list out the Flex 3 component and their Flex 4 Spark counter part.

Flex 3 MX Component Flex 4 spark Component
mx.controls.Button spark.components.Button
mx.controls.ButtonBar spark.components.ButtonBar
mx.controls.CheckBox spark.components.CheckBox
mx.controls.ComboBox spark.components.DropDownList (w/o editability)
mx.controls.HorizontalList spark.components.List (with a HorizontalLayout)
mx.controls.HRule spark.primitives.Line
mx.controls.HScrollBar spark.components.HScrollBar
mx.controls.HSlider spark.components.HSlider
mx.controls.Image spark.primitives.BitmapImage (w/o support for external images)
mx.controls.LinkBar spark.components.ButtonBar (with a custom skin)
mx.controls.LinkButton spark.components.Button (with a custom skin)
mx.controls.List spark.components.List
mx.controls.NumericStepper spark.components.NumericStepper
mx.controls.RadioButton spark.components.RadioButton
mx.controls.RadioButtonGroup spark.components.RadioButtonGroup
mx.controls.TextArea spark.components.TextArea
mx.controls.TabBar spark.components.TabBar
mx.controls.TextInput spark.components.TextInput
mx.controls.TileList spark.components.List (with a TileLayout)
mx.controls.ToggleButtonBar spark.components.ButtonBar
mx.controls.VideoDisplay spark.components.VideoPlayer
mx.controls.VRule spark.primitives.Line
mx.controls.VScrollBar spark.components.VScrollBar
mx.controls.VSlider spark.components.VSlider
mx.core.Application spark.components.Application
mx.core.Window spark.components.Window
mx.core.WindowedApplication spark.components.WindowedApplication
mx.containers.ApplicationControlBar spark.components.Application (with the controlBarContent)
mx.containers.Canvas spark.components.Group
mx.containers.ControlBar spark.components.Panel (with the controlBarContent property)
mx.containers.HBox spark.components.HGroup
mx.containers.Panel spark.components.Panel
mx.containers.Tile spark.components.Group (with a TileLayout)
mx.containers.VBox spark.components.VGroup

These components/containers are developed based on the UIComponent. There are few components/containers who is not having Spark counterpart. Following table demonstrate the list of components/container without Spark counterpart.

Flex 3 classes with no direct Flex 4 counterpart

mx.controls.Alert
mx.controls.ColorPicker
mx.controls.DataGrid
mx.controls.DateChooser
mx.controls.DateField
mx.controls.Menu
mx.controls.MenuBar
mx.controls.PopUpButton
mx.controls.PopUpMenuButton
mx.controls.ProgressBar
mx.controls.RichTextEditor
mx.controls.Tree
mx.containers.Accordion
mx.containers.DividedBox
mx.containers.Form
mx.containers.Grid
mx.containers.TabNavigator
mx.containers.TitleWindow
mx.containers.ViewStack

I am very excited about new architecture in Flex 4. I know you all too.

I will come up with some tutorial very soon in Flex 4.

Read more...

Saturday, April 24, 2010

Flex 3: Dispatch custom event

In this tutorial, I will walk through the Custom Even handling in Flex 3. Like Flex 3 inbuilt events, you can dispatch your custom event from the custom component. To do this we need to create an Custom Event class inherited from Flex based Event class. After this you can dispatch this custom event from your component or class using dispatch event function. Even you can add this event inline to your custom component tag in mxml file. To get the inline event property we need to set Metadata for the custom Event in component mxml.

In this tutorial, we will create an application which will have login form. And on login we will dispatch the custom LOGIN Event. To complete this application it will need to create following files.

  • Login.mxml

  • LoginEvent.as

  • Main.mxml


To start with, we will create an flex application in Flex Builder. While creating the project give your main mxml application file name as Main.mxml

Next, we will create the Login component, which will have the simple login form. This form will have two elements as, User Id: and Password:. To create this mxml component first we will set the folder structure to allocate the respective files. We will keep Component within src.view.components folder, and custom events within src.event folder.

First create these folders in src folder as show in the below image.



Now we are ready with packages, Next we will create the MXML Component named Login.mxml within the src.view.components folder. This Login.mxml will be based on Panel with no default width and height.

Replace following code to complete the Login Form.
<?xml version="1.0" encoding="utf-8"?>
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" title="Login" width="302" height="152">
<mx:Form width="100%">
<mx:FormItem label="User ID">
<mx:TextInput id="userid" />
</mx:FormItem>
<mx:FormItem label="Password">
<mx:TextInput id="password" displayAsPassword="true" />
</mx:FormItem>
<mx:FormItem>
<mx:Button id="btnLogin" label="Login" click="loginHandler()"/>
</mx:FormItem>
</mx:Form>
</mx:Panel>
In above code snippet, we have created the simple login Form containing two input field, User Id and Password respectively and one Login button.

We need to dispatch custom Login Event on Login Button click, For this first we have to create LoginEvent class.
Create LoginEvent class within src.events package. Make sure you extend this class to flex inbuilt Event class. There are few things we need to follow to create custom event.

You are require to override the Event.clone() method. This method will return the clone reference of your custom event i.e. LoginEvent.
You can create your custom properties that are required by the custom event. In our example LoginEvent will need to have userId and passWord.

In LoginEvent class add following code snippet to complete the CustomEvent class.
package events
{
import flash.events.Event;

public class LoginEvent extends Event
{
public static const LOGIN:String = 'login';

public var userId:String = '';
public var password:String = '';

public function LoginEvent(type:String, userId:String, password:String, bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);

this.userId = userId;
this.password = password;
}

override public function clone():Event {
return new LoginEvent(type, userId, password);
}
}
}
In the above code snippet, We have created the static const for event type, this we will use when we will dispatch or add event. Also we have created the two public properties userId and password, which we will send along with event when we dispatch this event.

Now we are ready with LoginEvent class, next we have to dispatch this event when user clicks on the Login button from the Login.mxml. Open Login.mxml file and add click handler function for Login button. In this function we will dispatch the LoginEvent along with userId and password property. Add this function in your Script tag within Login.mxml as shown below.
 <mx:Script>
<![CDATA[
import events.LoginEvent;
private function loginHandler():void
{
this.dispatchEvent(new LoginEvent(LoginEvent.LOGIN),userid.text, password.text)
}
]]>
</mx:Script>

If you noticed in above code, we have dispatch the LoginEvent on loginHandler function. We are ready with custom login component which will dispatch the Login event. But to add this custom login Event inline to the Login tag we need to se the metadata in Login.mxml. To do this add following code just above the Script tag.
<mx:Metadata>
[Event(name="login", type="events.LoginEvent")]
</mx:Metadata>
Remember you the name what we have mention in the name property above will be used in the Login tag as inline event property.

Now your complete Login.mxml will look like as below.
<?xml version="1.0" encoding="utf-8"?>
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" title="Login" width="302" height="152">
<mx:Metadata>
[Event(name="login", type="events.LoginEvent")]
</mx:Metadata>
<mx:Script>
<![CDATA[
import events.LoginEvent;
private function loginHandler():void
{
this.dispatchEvent(new LoginEvent(LoginEvent.LOGIN),userid.text, password.text)
}
]]>
</mx:Script>
<mx:Form width="100%">
<mx:FormItem label="User ID">
<mx:TextInput id="userid" />
</mx:FormItem>
<mx:FormItem label="Password">
<mx:TextInput id="password" displayAsPassword="true" />
</mx:FormItem>
<mx:FormItem>
<mx:Button id="btnLogin" label="Login" click="loginHandler()"/>
</mx:FormItem>
</mx:Form>
</mx:Panel>
Now we will add this custom component in the Main.mxml file and we will check whether we are getting the LOGIN event from Login.mxml component. To do so add following code in your Main.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application layout="vertical"
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:components="view.components.*">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import events.LoginEvent;

private function loginHandler(event:LoginEvent):void
{
Alert.show('Loign Event Handled Successfully for user id '+event.userId);
}
]]>
</mx:Script>
<components:Login login="loginHandler(event)"/>
</mx:Application>
If you notice in above code, we have added custom Loign component. And if you see the namespace for Login tag is components. We have added metadata for login event in Login.mxml and that we have used inline to the <components:Login> tag.

This is how we can use the Custom component in Flex.

I hope this will help.

View Demo here.

Read more...