Quick Start
Page Contents:
You can download this Quick Start as a Flash Builder FXP or Zip file. It's also available in the Swiz Examples repository on GitHub, along with more examples.
A Lightning Look at Configuration
Configuring Swiz in your Flex or AIR application is very straightforward: declare Swiz
, define the beanProviders
and config
properties, and optionally define one or more loggingTargets
to view debugging messages. Here is an example:
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:view="org.swizframework.quickswiz.view.*" xmlns:config="org.swizframework.quickswiz.config.*" xmlns:swiz="http://swiz.swizframework.org"> <fx:Declarations> <swiz:Swiz> <!-- BeanProviders simply contain the non-display objects that Swiz should process. --> <swiz:beanProviders> <config:Beans /> </swiz:beanProviders> <swiz:loggingTargets> <swiz:SwizTraceTarget id="myTraceTarget" /> </swiz:loggingTargets> <swiz:config> <!-- The eventPackages value tells Swiz the path to your Event classes, and viewPackages is an optional value that speeds up the processing of display classes. --> <swiz:SwizConfig eventPackages="org.swizframework.quickswiz.event.*" viewPackages="org.swizframework.quickswiz.view.*" /> </swiz:config> </swiz:Swiz> </fx:Declarations> <s:layout> <s:VerticalLayout horizontalAlign="center" paddingTop="20" /> </s:layout> <view:UserForm id="userForm" /> </s:Application>
Non-visual components that you want Swiz to manage are defined in a BeanProvider
tag. Any beans that you define within the BeanProvider
are processed by Swiz for dependency injection and the creation of event handlers. In the following example, a UserService
and a UserController
are created:
<swiz:BeanProvider xmlns:swiz="http://swiz.swizframework.org" xmlns:service="org.swizframework.quickswiz.service.*" xmlns:controller="org.swizframework.quickswiz.controller.*"> <service:UserService id="userService"/> <controller:UserController id="userController"/> <!-- We'll use the Swiz ServiceHelper to help simulate a server-side call. --> <swiz:ServiceHelper id="serviceHelper" /> </swiz:BeanProvider>
The "Big Three": Dependency Injection, Event Handling, and Server Interaction
The three most commonly used features of Swiz are its dependency injection capabilities, its event handling features, and its server interaction utilities. Let's look at how each of these work.
Adding Dependency Injection
Dependencies are injected by using [Inject]
metadata. In this example, the UserService
is injected into the UserController
:
package org.swizframework.quickswiz.controller { import org.swizframework.quickswiz.model.User; import org.swizframework.quickswiz.service.UserService; public class UserController { [Inject] public var userService : UserService; [Bindable] public var currentUser : User; } }
In addition to injecting a bean, you can inject individual bean properties. In this example, the currentUser
property of the UserController
is injected into a UserForm
visual component. Note that it is not necessary for the UserForm
to be declared as a bean in the BeanProviders
tag. When visual components are added to the display list, Swiz automatically inspects them and processes any metadata tags that are found.
<s:Panel xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx"> <fx:Script> <![CDATA[ import org.swizframework.quickswiz.event.UserEvent; import org.swizframework.quickswiz.model.User; [Bindable] [Inject( source="userController.currentUser", bind="true" )] /** * We could inject the whole controller instance, but we only need * one property from the controller, the current user, so we just * inject that property. */ public var user : User; ]]> </fx:Script> <mx:Form> <mx:Text id="userId" text="{isNaN( user.id ) ? 'N/A' : user.id}" /> <s:TextInput id="firstName" text="{user.firstName}" /> <s:TextInput id="lastName" text="{user.lastName}" /> <s:TextInput id="email" text="{user.email}" /> <s:Button label="Save" /> </mx:Form> </s:Panel>
Dispatching and Handling Events
When using Swiz, you dispatch standard Flex events. In this example, we've expanded the UserForm
to create and dispatch an event when the form button is clicked. Swiz listens for events being dispatched within the display list and handles them automatically.
<s:Panel xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx"> <fx:Script> <![CDATA[ import org.swizframework.quickswiz.event.UserEvent; import org.swizframework.quickswiz.model.User; [Bindable] [Inject( source="userController.currentUser", bind="true" )] /** * We could inject the whole controller instance, but we only need * one property from the controller, the current user, so we just * inject that property. */ public var user : User; /** * Handle the user hitting the save button. We capture the form data * and dispatch a standard Flex event. No Swiz-specific events or * special central dispatcher needed! */ private function saveUser() : void { user.firstName = firstName.text; user.lastName = lastName.text; user.email = email.text; var event : UserEvent = new UserEvent( UserEvent.SAVE_USER_REQUESTED ); event.user = user; dispatchEvent( event ); } ]]> </fx:Script> <mx:Form> <mx:Text id="userId" text="{isNaN( user.id ) ? 'N/A' : user.id}" /> <s:TextInput id="firstName" text="{user.firstName}" /> <s:TextInput id="lastName" text="{user.lastName}" /> <s:TextInput id="email" text="{user.email}" /> <s:Button label="Save" click="saveUser()" /> </mx:Form> </s:Panel>
A look at the UserEvent
confirms that this is just a simple, standard event. The only thing to note here is that the event has bubbles
set to true
. This allows the event to bubble up the display list so that it can be handled by Swiz:
package org.swizframework.quickswiz.event { import org.swizframework.quickswiz.model.User; import flash.events.Event; public class UserEvent extends Event { public static const SAVE_USER_REQUESTED : String = "saveUser"; public var user : User; /** * This is just a normal Flex event. The only thing to note is that we set 'bubbles' to true, * so that the event will bubble up the display list, allowing Swiz to listen for your events. */ public function UserEvent( type:String ) { super( type, true ); } } }
We've seen how to dispatch events from the display list, but how do we handle the events? Swiz provides a [EventHandler]
metadata tag to do this. In the example below, we have expanded the UserController
to add an event handler method. In this case, when Swiz encounters an event of type UserEvent.SAVE_USER_REQUESTED
, it will automatically invoke the saveUser
method in the UserController
. By specifying a value of "user" for the properties
attribute, Swiz will locate the user
property in the UserEvent
and pass this as a parameter to the handler method:
package org.swizframework.quickswiz.controller { import org.swizframework.quickswiz.model.User; import org.swizframework.quickswiz.service.UserService; public class UserController { [Inject] public var userService : UserService; [Bindable] public var currentUser : User; [PostConstruct] /** * [PostConstruct] methods are invoked after all dependencies are injected. * In this example, we set up a default user after the bean is created. */ public function createDefaultUser() : void { currentUser = new User(); } [EventHandler( event="UserEvent.SAVE_USER_REQUESTED", properties="user" )] /** * Perform a server request to save the user */ public function saveUser( user : User ) : void { // TODO: Add server interaction } } }
One last feature to note regarding event dispatching. We've seen how an event dispatched from the display list will bubble up until it is processed by Swiz. But what about dispatching events from non-visual components like controllers and services? Swiz offers the [Dispatcher]
metadata tag to meet this need. In the UserService
shown below, Swiz will automatically inject an event dispatcher into the dispatcher
property. Any events dispatched though this dispatcher will also be processed by Swiz and trigger any event handler methods associated with the event:
package org.swizframework.quickswiz.service { import org.swizframework.quickswiz.model.User; import flash.events.IEventDispatcher; import mx.rpc.AsyncToken; import org.swizframework.utils.services.MockDelegateHelper; public class UserService { [Dispatcher] /** * The [Dispatcher] metadata tag instructs Swiz to inject an event dispatcher. * Events dispatched via this dispatcher can trigger methods annotated with [EventHandler]. */ public var dispatcher : IEventDispatcher; /** * To avoid a live server dependency, we use a Swiz * helper class to let us create fake AsyncTokens */ private var mockHelper : MockDelegateHelper; public function UserService() { mockHelper = new MockDelegateHelper(); } /** * In a real app, we'd invoke a RemoteObject, HTTPService, etc. * For this simple example, we'll set a random ID on the User * to simulate the process of saving a User. */ public function saveUser( user : User ) : AsyncToken { user.id = Math.round( Math.random() * 100 ); return mockHelper.createMockResult( user ); } } }
Talking to the Server
Our UserController
can now respond when a save user event is dispatched. The final piece of the puzzle is having the application make a call to the server to actually save the user in a database. Typically, Flex requries you to manually create Responder
objects to attach to AsyncTokens
that will handle ResultEvent
and FaultEvent
. Swiz offers some helpful features to sidestep these manual processes. Below, you see the final version of our UserController
. Because it has the Swiz helper object ServiceHelper
injected, we can use its executeServiceCall()
method. This method will automatically obtain the AsyncToken
for the RPC call and create Responder
objects. In this case, we call userService.saveUser()
, and specify handleSaveUserResult
to handle the successful response from the server. Although it is not shown here, we can also specify a method to use as the fault handler.
package org.swizframework.quickswiz.controller { import org.swizframework.quickswiz.model.User; import org.swizframework.quickswiz.service.UserService; import mx.controls.Alert; import mx.rpc.events.ResultEvent; import org.swizframework.utils.services.ServiceHelper; public class UserController { [Inject] public var userService : UserService; [Inject] public var serviceHelper : ServiceHelper; [Bindable] public var currentUser : User; [PostConstruct] /** * [PostConstruct] methods are invoked after all dependencies are injected. * In this example, we set up a default user after the bean is created. */ public function createDefaultUser() : void { currentUser = new User(); } [EventHandler( event="UserEvent.SAVE_USER_REQUESTED", properties="user" )] /** * Perform a server request to save the user */ public function saveUser( user : User ) : void { serviceHelper.executeServiceCall( userService.saveUser( user ), handleSaveUserResult ); } /** * Handle the server call result */ private function handleSaveUserResult( event : ResultEvent ) : void { // Show an Alert just to make it obvious that the save was successful. Alert.show( 'User saved successfully!' ); } } }
There's More Where That Came From
This quick tour has shown how easy it is to configure Swiz and use its core features. But Swiz offers much more than this! Please read the User Guide, Best Practices, and Advanced Topics to learn more.