Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
frank_stdle
Participant
0 Kudos

Flash islands in SAP

Recognizing the limited flexibility of the standard Web Dynpro UI components, SAP has provided flash islands (and Silverlight island) as an option for embedding visually rich and interactive UI components into Web Dynpro applications. If you have seen some of the available tutorials (look here ) or perhaps created some flash components yourself, you will already have a sense of the vast possibilities offered by the Flex framework with which flash applications are built.  Often you will build no more than a simple barchart or similar, but also more complex flash applications can be integrated into a Web Dynpro application. While building such a complex application - a highly visual and interactive dashboard -  my code base quickly grew out of control, and I saw the need to organize my code in a better way.  Web Dynpro applications are based on the Model-View-Controller (MVC) pattern, so since the MVC pattern is something we all know and love (and if you don't you better read up on it here), it makes sense to apply this pattern to your flash application as well. In this blog I will present a simple method of applying MVC to a flash application running within a Web Dynpro flash island.

MVC, the short story

In short, MVC works as follows: the user will interact with UI components (views) in the application, perhaps clicking on a chart or a table. The Controller will react to the user event that is assigned to the particular user action (mouse click, text entered etc.). The Controller will take some action, typically updating the Model which is the representation of the state (data) in the application. When the Model is updated with changed or new data, the views that are bound to the Model will update accordingly.

MVC in flash applications

Most flash applications embedded in a flash island will consist of one screen. In the context of MVC all UI elements can be considered as views, not to be confused with screens or Web Dynpro views. Applying the MVC pattern will make sense even if your flash application consists of only one screen. For instance, for a dashboard, typically multiple UI components are presented on the screen at the same time, each representing data in different forms, such as text, a chart, a table and so on.  There are several frameworks, such as PureMVC and Cairngorm, available for developing flash MVC application. In building my applications I did not try any of these frameworks, as I feared they would introduce unnecessary complexity and overhead to my application.

A simple application

If you have followed any of the availble tutorials on developing flash islands, you will typically have created a Flex project with an application such as this:

MyDashboard_ver1.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" minWidth="955"
                minHeight="600" initialize="initApp()">
   
    <mx:Script>
        <![CDATA[
            import mx.collections.ArrayCollection;           
            import sap.FlashIsland;
                                
            [Bindable]
            public var profitAndExpenses:ArrayCollection; //Expenses and profit per period
           
            public function initApp():void
            {
                FlashIsland.register(this);    
            }
           
            public function eventOnUserAction(eventObj:MouseEvent):void {
                // Do something when user clicks on a bar series
            }
           
        ]]>
       
    </mx:Script>
   
    <mx:Panel title="Bar Chart">
        <mx:BarChart id="expenses" dataProvider="{profitAndExpenses}" showDataTips="true">
            <mx:verticalAxis>
                <mx:CategoryAxis
                    dataProvider="{profitAndExpenses}"
                    categoryField="Month"
                    />
            </mx:verticalAxis>
            <mx:series>
                <mx:BarSeries
                    yField="Month"
                    xField="Profit"
                    displayName="Profit"
                    click="eventOnUserAction(event)"
                    />
                <mx:BarSeries
                    yField="Month"
                    xField="Expenses"
                    displayName="Expenses"
                    />
            </mx:series>
        </mx:BarChart>
    </mx:Panel>
   
</mx:Application>

We want to apply the MVC pattern to this applications, so we will create two new classes:

MyDashboardModel.as

package
{
    import mx.collections.ArrayCollection;

    public class MyDashboardModel
    {
       
        //Instance
        public static var instance:MyDashboardModel;
       
        [Bindable]
        public var profitAndExpenses:ArrayCollection; //Expenses and profit per period
       
        public function MyDashboardModel():void
        {
            if (instance != null) {
                throw( new Error("There can be only one instance of MyDashboardModel. " +
                       "Use MyDashboardModel.getInstance() instead."));
            }
        }
       
        public static function getInstance():MyDashboardModel {
            if (instance == null) {
                instance = new MyDashboardModel;
            }
           
            return instance;
        }
       
    }
}

MyDashboardController.as

package
{
    import flash.events.MouseEvent;

    public class MyDashboardController
    {
       
        //Instance
        public static var instance:MyDashboardController;
       
        public function MyDashboardController():void
        {
            if (instance != null) {
                throw( new Error("There can be only one instance of MyDashboardController. " +
                       "Use MyDashboardController.getInstance() instead."));
            }
        }
       
        public static function getInstance():MyDashboardController {
            if (instance == null) {
                instance = new MyDashboardController;
            }
           
            return instance;
        }
       
        public function eventOnUserAction(eventObj:MouseEvent):void {
            // Do something when user clicks on a bar series
        }

    }
}

As you might suspect these two classes will serve as the Controller and Model in our application. Both classes return a single instance through the getInstance() method. The profitAndExpenses data structure has been moved to  MyDashboardModel , and the event handler  eventOnUserAction() has been moved to  MyDashboardController. To further clean up the application we can also move the bar chart into a separate MXML component:

ProfitAndExplenses.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="400" height="300">
   
    <mx:Script>
        <![CDATA[
            [Bindable]
            private var model:MyDashboardModel = MyDashboardModel.getInstance();
            private var controller:MyDashboardController = MyDashboardController.getInstance();    
        ]]>
    </mx:Script>
   
    <mx:BarChart id="expenses" dataProvider="{model.profitAndExpenses}" showDataTips="true">
        <mx:verticalAxis>
            <mx:CategoryAxis
                dataProvider="{model.profitAndExpenses}"
                categoryField="Month"
                />
        </mx:verticalAxis>
        <mx:series>
            <mx:BarSeries
                yField="Month"
                xField="Profit"
                displayName="Profit"
                click="controller.eventOnUserAction(event)"
                />
            <mx:BarSeries
                yField="Month"
                xField="Expenses"
                displayName="Expenses"
                />
        </mx:series>
    </mx:BarChart>
</mx:Panel>

The profitAndExpenses component references the model and the controller. The dataprovider for the bar chart is "bound" to profitAndExpenses data structure in the model using curly braces. This means that whenever the data structure in the model is updated, the bar chart will also be updated.  Note that to be able to bind to profitAndExpenses, the data structure must be preceded with the [Bindable] tag in the model. The compiler will issue a warning if you forget this.  Binding views to data in the model is an extremely simple and powerful feature of Actionscript. Your views (UI elements) will update automatically whenever the controller manipulates the model or new data is communicated from the WDA.  Now the main application file can be cleaned up as follows:

MyDashboard_ver2.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" minWidth="955"
                minHeight="600" initialize="initApp()" xmlns:local="*">
   
    <mx:Script>
        <![CDATA[
            import sap.FlashIsland;
           
            private var model:MyDashboardModel = MyDashboardModel.getInstance();
           
            public function initApp():void
            {
                FlashIsland.register(model);       
            }
               
        ]]>
       
    </mx:Script>
   
    <local:ProfitAndExpenses />
   
</mx:Application>

As the application grows, more data structures can be added to the model, more interaction logic can be added to the controller, and new MXML UI components (views) are created and embedded into the main application file. All views refrence the same controller and model, so that whenever the model is updated each bound view is also updated without the need for implementing any additional logic.

Conclusion

MVC is probably the one of the most common architectural patterns in software engineering. It is also a testament to the simplicity and power of MVC that it can easily be implemented using just built-in features of a language without the need for a framework. I have used the simple scheme outlined above with great success in a fairly large application consisting of about 40 actionscript classes and MXML components and multiple views.

5 Comments
Labels in this area