[Flex 4] Sử dụng State với Flex 4

Trong bài viết giới thiệu về Flex 4 tôi đã có đề cập đến sự cải tiến trong việc sử dụng State của Flex 4 so với Flex 3. Bài viết này tôi sẽ trình bày chi tiết hơn sự khác biệt giữa Flex 3 và Flex 4 trong việc sử dụng State. Trước hết chúng ta hãy nghiên cứu một kịch bản như sau:

Ứng dụng cần một form cho phép user đăng nhập (sign in) và nếu họ chưa có tài khoản thì cho phép họ đăng ký (sign up) trên chính form đó. Như vậy Form cần có 2 trạng thái là Sign In và Sign Up để User có thể chuyển đổi giữa 2 state đó bằng 1 nút bấm. Khi ở trạng thái Sign In, Form có 2 field là Email và Password, khi chuyển sang trạng thái Sign Up, Form sẽ có thêm 2 field nữa là First Name và Last Name.

Sign Up state - created with Halo components

Màn hình đăng ký

SignIn state - created with Halo components

Màn hình đặng nhập

Để chuyển đổi giữa 2 trạng thái của form, với Flex 3,  khi chuyển đổi giữa các State, tôi phải làm khá nhiều thao tác như  đặt lại nội dung có các label, tiến hành remove / add các component và thậm chí phải đặt lại cái listener khác nhau. Chính vì vậy mà một business đơn giản nhưng lại ngốn khá nhiều dòng code.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application name="Screen_screens_test"
        xmlns:mx="http://www.adobe.com/2006/mxml"
        layout="vertical"
        verticalAlign="center"
        backgroundColor="white"
		horizontalScrollPolicy="off" verticalScrollPolicy="off"
        initialize="initializeHandler();">

    <mx:Script>
        <![CDATA[
			import mx.controls.Alert;
			import mx.utils.StringUtil;
			import flash.events.MouseEvent;

            private function initializeHandler():void {
				this.currentState = null;
            }

			private function changeStateHandler(e: MouseEvent): void {
				this.currentState = this.currentState == null ? "signUpState" : null;
			}
        ]]>
    </mx:Script>
	<mx:states>
		<mx:State name ="signUpState">
			<mx:SetProperty target="{mainPanel}" name="height" value="220" />
			<mx:SetProperty target="{mainPanel}" name="title" value="Sign Up" />
			<mx:SetProperty target="{formitem1}" name="label" value="First Name" />
			<mx:SetProperty target="{formitem2}" name="label" value="Last Name" />
			<mx:SetProperty target="{textInput2}" name="displayAsPassword" value="false" />

			<mx:AddChild relativeTo="{mainForm}" position="lastChild">
				<mx:FormItem label="Email" width="100%">
					<mx:TextInput id="textInput3" width="100%" />
				</mx:FormItem>
			</mx:AddChild>
			<mx:AddChild relativeTo="{mainForm}" position="lastChild">
				<mx:FormItem label="Password" width="100%">
					<mx:TextInput id="textInput14" width="100%" displayAsPassword="true" />
				</mx:FormItem>
			</mx:AddChild>
			<mx:SetProperty target="{signInUpButton}" name="label" value="Sign Up" />
			<mx:SetProperty target="{stateLinkButton}" name="label" value="Back to Sign In screen" />
		</mx:State>
	</mx:states>

	<mx:transitions>
		<mx:Transition fromState="*" toState="*">
			<mx:Parallel duration="300">
				<mx:Resize target="{mainPanel}"/>
				<mx:Fade target="{mainForm}" alphaFrom="0" alphaTo="1"/>
			</mx:Parallel>
		</mx:Transition>
	</mx:transitions>

	<mx:Panel id="mainPanel" title="Sign In" width="50%" height="200">
		<mx:Form id="mainForm" width="100%" height="100%">
			<mx:FormItem id="formitem1" 	label="Email" width="100%">
				<mx:TextInput id="textInput1" width="100%"/>
			</mx:FormItem>
			<mx:FormItem id="formitem2" label="Password" width="100%">
				<mx:TextInput id="textInput2" width="100%" displayAsPassword="true" />
			</mx:FormItem>
		</mx:Form>
		<mx:ControlBar horizontalAlign="right">
			<mx:LinkButton id="stateLinkButton" label ="Dont have account ? Signup now" click="changeStateHandler(event)" />
			<mx:Spacer width="100%" />
			<mx:Button id="signInUpButton" label="Sign In"/>
		</mx:ControlBar>
	</mx:Panel>
</mx:Application>

Với Flex 4 thì bạn không cần phải làm nhiều thao tác như vậy. Hãy xem ví dụ trên khi được viết lại với Flex 4

<?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" 
			   initialize="{initializeHandler()}"
			   minWidth="955" minHeight="600">
	<fx:Declarations>
		<!-- Place non-visual elements (e.g., services, value objects) here -->
	</fx:Declarations>
	<fx:Script>
		<![CDATA[
			import mx.controls.Alert;
			import mx.utils.StringUtil;
			import flash.events.MouseEvent;
			
			private function initializeHandler():void {
				this.currentState = "signInState";
			}
			
			private function changeStateHandler(e: MouseEvent): void {
				this.currentState = this.currentState == "signInState" ? "signUpState" : "signInState";				
			}	
		]]>
	</fx:Script>
	
	<s:states>
		<s:State name="signInState"/>
		<s:State name="signUpState"/>
	</s:states>

	<s:transitions>
		<s:Transition fromState="*" toState="*">
			<s:Parallel duration="300">
				<s:Resize target="{mainPanel}" />
				<s:Fade target="{mainForm}" alphaFrom="0" alphaTo="1" />
			</s:Parallel>
		</s:Transition>
	</s:transitions>

	<s:layout>
		<s:VerticalLayout/>
	</s:layout>

	<mx:Panel id="mainPanel" width="50%" 
			  title.signInState="Sign In"  title.signUpState="Sign Up"
			  height.signInState="200" height.signUpState="220">
		<mx:Form id="mainForm" width="100%" height="100%">
			<mx:FormItem label="First name:" includeIn="signUpState" width="100%" >
				<s:TextInput id="firstNameText" width="100%"/>
			</mx:FormItem>
			<mx:FormItem label="Last name:" includeIn="signUpState" width="100%" >
				<s:TextInput id="lastNameText" width="100%"/>
			</mx:FormItem>
			<mx:FormItem label="Email" width="100%">
				<mx:TextInput id="emailText" width="100%"/>
			</mx:FormItem>
			<mx:FormItem label="Password" width="100%">
				<mx:TextInput id="passwordText" width="100%" displayAsPassword="true" />
			</mx:FormItem>
		</mx:Form>
		<mx:ControlBar horizontalAlign="right">
			<mx:LinkButton id="stateLinkButton" 
						   label.signInState ="Dont have account ? Signup now"
						   label.signUpState ="Back to Sign In screen" 
						   click="changeStateHandler(event)" />
			<mx:Spacer width="100%" />
			<mx:Button id="signInUpButton" label="Sign In"/>
		</mx:ControlBar>
	</mx:Panel>
</s:Application>

Với Flex 4 thì khái niệm state trở nên dễ hiểu hơn khi bạn có thể khai thác cú pháp dạng “thuộc tính theo từng state”, như là một Button của bạn có 3 trạng thái thì từng thuộc tính của nó cũng có 3 giá trị khác nhau ứng với từng trạng thái.  Ví dụ button trên Form có 3 trạng thái là Login thì label của nó là “Login”, đăng ký là “Register” và thoát là “Exit” … lúc đó bạn dễ dàng khai báo <s:Button label.login=”Login label.register=”Register” label.exit=”Exit”  /> . Tất nhiên là bạn phải khai báo 3 State đó từ trước. Ngoài ra, các thuộc tính includeIn và excludeFrom của các component dễ dàng cho phép bạn remove hoặc add component đó theo từng state mà không cần phải thực hiện addChild hoặc removeChild trong State  như với Flex 3.

2 thoughts on “[Flex 4] Sử dụng State với Flex 4

    • Đang tìm cái theme khác của wordpress để nó show code tốt hơn, hiện tại cái theme này display hình rất tốt.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s