December 11th, 2007 by Kyle
Tags: , , , , , , , ,
Posted in: Flex

I had a customer asking how to do this.
Sorting the datagrid sorts the underlying dataprovider.
Remember that things like ArrayCollections are just essentially views of the data. So adding an element to the underlying data, regardless of the position at which you add the new item, will not affect its position in the “view”. It will get added in its sorted position if the view is showing sorted data. The workaround to this is show in the simple sample below:

<mx:application xmlns:mx="http://www.adobe.com/2006/mxml" creationcomplete="init()">
    <mx:script>
        <!–[CDATA[
            import mx.collections.ArrayCollection;

            public var objs:ArrayCollection = new ArrayCollection();
            /*
             * initialize the dataprovider
             */

            private function init():void {

                var obj:Object = new Object();
                obj.name = "carry";
                objs.addItem(obj);

                obj = new Object();
                obj.name = "fred";
                objs.addItem(obj);

                obj = new Object();
                obj.name = "henry";
                objs.addItem(obj);

                obj = new Object();
                obj.name = "issac";
                objs.addItem(obj);

                obj = new Object();
                obj.name = "mary";
                objs.addItem(obj);

                obj = new Object();
                obj.name = "tom";
                objs.addItem(obj);

                obj = new Object();
                obj.name = "tom2";
                objs.addItem(obj);

                dg.dataProvider = objs;
            }

            import flash.utils.ByteArray;

            private function clone(source:Object):*
            {
                var myBA:ByteArray = new ByteArray();
                myBA.writeObject(source);
                myBA.position = 0;
                return(myBA.readObject());
            }

            private function addObj():void{

                var temp:Array = clone(objs.toArray());
                objs=new ArrayCollection(temp);
                dg.dataProvider=objs;

                var obj:Object = new Object();
                obj.name=;
                objs.addItemAt(obj, 0)

            }

        ]]–>
    </mx:script>
    <mx:button width="150" label="Add New Row" click="addObj()">
    <mx:datagrid id="dg" editable="true" width="50%" height="80%">
    <mx:columns>
        <mx:datagridcolumn headertext="Name" datafield="name">
            editable="true" />
    </mx:datagridcolumn>
</mx:columns>                                                  

</mx:datagrid>
</mx:button></mx:application>

Browse the source of this example.
Download a zipfile containing the source to this sample.

This movie requires Flash Player 9


No Comments »

December 5th, 2007 by Kyle
Tags: , , , , , , , , ,
Posted in: ActionScript, Flex

XML and ampersands do not mix well.
Flex uses mxml which is XML.
This can lead to issues when writing binding expressions in mxml tags for component properties when you are trying to write logical expressions using ‘and’.

Here is a simple sample that demonstrates how to escape the ampersands in the expression and how to create a logical expression that does not even use ‘and’, but achieves the same result.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
   
    <mx:Script>
        <![CDATA[
            [Bindable]
            public var bOne:Boolean=false;
            [Bindable]
            public var bTwo:Boolean=false;         
        ]]>
    </mx:Script>
   
    <mx:Button label="(click to toggle) bOne: {bOne}" click="bOne=!bOne"/>
    <mx:Button label="(click to toggle) bTwo: {bTwo}" click="bTwo=!bTwo"/>
   
    <mx:Label text="If bOne and bTwo are true, the buttons below will be Enabled"/>
    <!–escape the ampersands for the logical and operator –>
    <mx:Button label="enabled?" enabled="{(bOne &amp;&amp; bTwo)}"/>
    <!–or use this compounded logical statement which will evaluate to the same thing –>
    <mx:Button label="enabled?" enabled="{(bOne ? bTwo : false)}"/> 
   
</mx:Application>
 

Browse the source of this example.
Download a zipfile containing the source to this sample.

This movie requires Flash Player 9


4 Comments »

November 19th, 2007 by Kyle
Tags: , , , , , ,
Posted in: ActionScript, Flash Player

I had a customer who was having problems with linebreaks in her Flex code.
I had used linebreaks before with no problem until I realized that she was setting text with linebreaks in mxml and not setting properties dynamically as I had done in all instances in teh past when dealing with linebreaks.
I search the Adobe public bugbase and found this bug:

http://bugs.adobe.com/jira/browse/SDK-12649

I thought I’d write a simple app to demonstrate the problem and workarounds.

Here is the source for the app:

<mx:application xmlns:mx="http://www.adobe.com/2006/mxml">
    <mx:label id="ta1" height="75" width="250" text="This does not \nwrap">
    <mx:button label="click to set via actionscript" click="ta2.text=’Setting via actionscript and\nthis does wrap’">
    <mx:label id="ta2" height="75" width="250">
    <mx:label id="ta3" height="75" width="250" text="Alternatively with this workaround,{’\n‘}this wraps too">
</mx:label>
</mx:label></mx:button></mx:label></mx:application>

Browse the source of this example.
Download a zipfile containing the source to this sample.

This movie requires Flash Player 9


No Comments »

November 9th, 2007 by Kyle
Tags: , , , , ,
Posted in: Flex

Apparently this is something that happened in Flex 1.5 by default or was easily settable. It wasn’t too difficult in the Flex 2.x codebase, but I thought I’d post the solution anyways.

Here is the sample app:

<!– Simple example to demonstrate the MenuBar control. –>
<mx:application xmlns:mx="http://www.adobe.com/2006/mxml" creationcomplete="initCollections();">
    <mx:script>
        <!–[CDATA[
            import mx.controls.menuClasses.IMenuBarItemRenderer;
            import mx.controls.MenuBar;
            import mx.controls.menuClasses.MenuBarItem;

            import mx.events.MenuEvent;
            import mx.controls.Alert;
            import mx.collections.*;

            [Bindable]–>            public var menuBarCollection:XMLListCollection;

            private var menubarXML:XMLList =
                <>
                    <menuitem label="Menu1" data="top">
                        <menuitem label="MenuItem 1-A" data="1A">
                        <menuitem label="MenuItem 1-B" data="1B">
                    </menuitem>
                    <menuitem label="Menu2" data="top">
                        <menuitem label="MenuItem 2-A" type="check" data="2A">
                        <menuitem type="separator">
                        <menuitem label="MenuItem 2-B">
                            <menuitem label="SubMenuItem 3-A" type="radio">
                                groupName="one" data="3A"/>
                            <menuitem label="SubMenuItem 3-B" type="radio">
                                groupName="one" data="3B"/>
                        </menuitem>
                    </menuitem>
                    <menuitem label="Menu3" data="top">
                        <menuitem label="MenuItem 3-A" data="3A">
                        <menuitem label="MenuItem 3-B" data="3B">
                    </menuitem>
                    <menuitem label="Menu4" data="top">
                        <menuitem label="MenuItem 4-A" data="4A">
                        <menuitem label="MenuItem 4-B" data="4B">
                    </menuitem>
                </menuitem>;

            // Event handler to initialize the MenuBar control.
            private function initCollections():void {
                menuBarCollection = new XMLListCollection(menubarXML);
            }

            // Event handler for the MenuBar control’s itemClick event.
            private function menuHandler(event:MenuEvent):void  {
                // Don’t open the Alert for a menu bar item that
                // opens a popup submenu.
                if (event.item.@data != "top") {
                    Alert.show("Label: " + event.item.@label + "\n" +
                        "Data: " + event.item.@data, "Clicked menu item");
                }
            }

            private function onTopSelection(event:MenuEvent):void{
                var mb:MenuBar=event.target as MenuBar;
                var selectedIndex:int=mb.selectedIndex;

                for (var i:int=0;i<mb.menubaritems.length;i++){>
                    if(i==selectedIndex){
                        (mb.menuBarItems[i] as MenuBarItem).setStyle("fontWeight","bold");
                    }
                    else{
                        (mb.menuBarItems[i] as MenuBarItem).setStyle("fontWeight","normal");
                    }
                }
            }

         ]]>
    </mb.menubaritems.length;i++){>

    <mx:panel title="MenuBar Control Example" height="75%" width="75%">
        paddingTop="10" paddingLeft="10">

        <mx:label width="100%" color="blue">
           text="Select a menu item."/>

        <mx:menubar labelfield="@label" itemclick="menuHandler(event);">
            dataProvider="{menuBarCollection}" change="onTopSelection(event)" />

    </mx:menubar>
</mx:label>
</mx:panel></menuitem></menuitem></menuitem></menuitem></menuitem></menuitem></menuitem></menuitem></menuitem></mx:script></mx:application>

Browse the source of this example.
Download a zipfile containing the source to this sample.

This movie requires Flash Player 9


1 Comment »

November 1st, 2007 by Kyle
Tags: , , ,
Posted in: Flex

I had a customer that noticed that when you disable the datagrid, it does not “gray out” like other components. I went digging around in the code and found that the datagrid did in fact “gray out” but the opacity of the background blocked the effect out. The header also didn’t seem to “gray out”, so I took care of both issues in my extension to dataGrid as shown below.

Here is my simple app to demonstrate the issue and workaround:

<mx:application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:my="*">

    <mx:xmllist id="employees">
        <iployee>
            <name>Christina Coenraets</name>
<phone>555-219-2270</phone>
            <iail>ccoenraets@fictitious.com</iail>
            <active>true</active>
        </iployee>
        <iployee>
            <name>Joanne Wall</name>
<phone>555-219-2012</phone>
            <iail>jwall@fictitious.com</iail>
            <active>true</active>
        </iployee>
        <iployee>
            <name>Maurice Smith</name>
<phone>555-219-2012</phone>
            <iail>maurice@fictitious.com</iail>
            <active>false</active>
        </iployee>
        <iployee>
            <name>Mary Jones</name>
<phone>555-219-2000</phone>
            <iail>mjones@fictitious.com</iail>
            <active>true</active>
        </iployee>
    </mx:xmllist>

        <mx:label text="Default DataGrid">
        <mx:datagrid id="dg" width="100%" height="100%" rowcount="5" dataprovider="{employees}">
            <mx:columns>
                <mx:datagridcolumn datafield="name" headertext="Name">
                <mx:datagridcolumn datafield="phone" headertext="Phone">
                <mx:datagridcolumn datafield="email" headertext="Email">
            </mx:datagridcolumn>
        </mx:datagridcolumn>

        <mx:label text="Custom DataGrid">
        <my:mydatagrid id="mydg" width="100%" height="100%" rowcount="5" dataprovider="{employees}">
            <my:columns>
                <mx:datagridcolumn datafield="name" headertext="Name">
                <mx:datagridcolumn datafield="phone" headertext="Phone">
                <mx:datagridcolumn datafield="email" headertext="Email">
            </mx:datagridcolumn>
        </mx:datagridcolumn>

<mx:button label="enable/disable DG" click="mydg.enabled=!mydg.enabled;dg.enabled=!dg.enabled">

</mx:button>
</mx:datagridcolumn></my:columns></my:mydatagrid></mx:label></mx:datagridcolumn></mx:columns></mx:datagrid></mx:label></mx:application>

Here is my custom extension to datagrid:

<mx:datagrid xmlns="*" xmlns:mx="http://www.adobe.com/2006/mxml">

    <mx:script>
        <!–[CDATA[

        private var original_backgroundAlpha:Number;
        private var original_headerColors:Array;       

        override public function set enabled(value:Boolean):void
        {
            if(isNaN(original_backgroundAlpha)){
                original_backgroundAlpha=1;
            }

            if(value){
                this.setStyle("backgroundAlpha",original_backgroundAlpha);
                if(original_headerColors){
                    this.setStyle("headerColors",original_headerColors);
                }
            }
            else{
                original_backgroundAlpha=this.getStyle("backgroundAlpha");
                original_headerColors=this.getStyle("headerColors");
                this.setStyle("backgroundAlpha",original_backgroundAlpha*.75)

                var bgDC:Number=this.getStyle("backgroundDisabledColor");

                this.setStyle("headerColors",[bgDC,bgDC]–>         }

            super.enabled = value;
        }
        ]]>
    </mx:script>

</mx:datagrid>

Here is the running application:

This movie requires Flash Player 9

Browse the source of this example.
Download a zipfile containing the source to this sample.


No Comments »

I have come across a few cases where it was useful to have the column and row positions within an itemRenderer and so have made this sample to demonstrate how to do that.

Here is the application code:

<mx:application xmlns:mx="http://www.adobe.com/2006/mxml">
    <mx:script>
        <!–[CDATA[
            import mx.events.DataGridEvent;
            import mx.collections.ArrayCollection;

            private static var object1:Object = new Object();
                                object1.name = "Object 1";

            private static var object2:Object = new Object();
                                object2.name = "Object 2";

            private static var object3:Object = new Object();
                                object3.name = "Object 3";

            private static var object4:Object = new Object();
                                object4.name = "Object 4";

            private static var object5:Object = new Object();
                                object5.name = "Object 5";

            private static var object6:Object = new Object();
                                object6.name = "Object 6";

            private static var object7:Object = new Object();
                                object7.name = "Object 7";

            private var things:Array = [object1, object2, object3, object4, object5, object6, object7]–>
            [Bindable]
            public var thingsAC:ArrayCollection = new ArrayCollection(things);

        ]]>
    </mx:script>

    <mx:datagrid id="dg" width="510" height="100">
         draggableColumns="false" dataProvider="{thingsAC}"
         horizontalScrollPolicy="on"
         rowCount="4">

        <mx:columns>
            <mx:datagridcolumn width="200" headertext="Name" datafield="name">
            <mx:datagridcolumn width="200" headertext="Column 2" itemrenderer="MyIR">
            <mx:datagridcolumn width="200" headertext="Column 3" itemrenderer="MyIR">
            <mx:datagridcolumn width="200" headertext="Column 4" itemrenderer="MyIR">
        </mx:datagridcolumn>
    </mx:datagridcolumn>

</mx:datagridcolumn>
</mx:datagridcolumn></mx:columns></mx:datagrid></mx:application>

Here is the code for my itemRenderer:

<mx:vbox xmlns:mx="http://www.adobe.com/2006/mxml" horizontalalign="center">
    implements="mx.controls.listClasses.IDropInListItemRenderer"
    preinitialize ="init();">

    <mx:script>
    <!–[CDATA[
        import mx.controls.DataGrid;
        import mx.controls.dataGridClasses.DataGridListData;
        import mx.controls.listClasses.BaseListData;
        import flash.events.Event;
        import mx.collections.ArrayCollection;        

        [Bindable]–>       public var _lbl:String;

        private function onChange(event:Event):void{
            var myListData:DataGridListData = DataGridListData(listData);
        }

        private var _listData:BaseListData;
        private var myDG:DataGrid;

        public function get listData():BaseListData {
          return _listData;
        }
        public function set listData( value:BaseListData ):void {
            _listData = value;
            myDG = _listData.owner as DataGrid;

        }  

        public function init():void {
            addEventListener("dataChange", handleDataChanged);
        }    

        public function handleDataChanged(event:Event):void {
            // Cast listData to DataGridListData.
            var myListData:DataGridListData = DataGridListData(listData);

            var row:int=myListData.rowIndex+myDG.verticalScrollPosition;
            //to make 1 based
            var col:int=myListData.columnIndex+1;

            _lbl="row: " + String(row) +
                " column: " + String(col);

        }    

        ]]>
    </mx:script>
    <mx:label id="lbl" text="{_lbl}">
</mx:label>
</mx:vbox>

Here is the running application:

This movie requires Flash Player 9

Browse the source of this example.
Download a zipfile containing the source to this sample.


No Comments »

October 26th, 2007 by Kyle
Tags: , , , , , ,
Posted in: Flex

I was helping a customer with a simple sample and couldn’t find one that was specifically what I needed. The docs did have a sample for filtering an arraycollection bound to a combobox (I think) and this wasn’t much of a stretch, but I thought it would be useful to post the sample for the datagrid scenario so that it was no stretch.

Here is the application code:

<mx:application xmlns:mx="http://www.adobe.com/2006/mxml">
    <mx:script>
        <!–[CDATA[
            import mx.collections.*;
            import mx.events.ItemClickEvent;            

            private var selectedRegion:String;

            public function regionFilterFunc(item:Object):Boolean {
                if (selectedRegion=="all")
                    return true
                else
                    return item.region == selectedRegion;
            }

            // Function to apply the filter function the ICollectionView.
            public function filterAC(event:ItemClickEvent):void {
                selectedRegion=event.label;
                myAC.filterFunction=regionFilterFunc;
                //Refresh the collection view to apply the filter.
                myAC.refresh();
            }

        ]]–>
    </mx:script>

    <!– An ArrayCollection with an array of objects. –>
    <mx:arraycollection id="myAC">
        <mx:array id="myArray">
            <mx:object state="LA" city="Baton Rouge" region="west">
            <mx:object state="NH" city="Concord" region="east">
            <mx:object state="TX" city="Austin" region="west">
            <mx:object state="MA" city="Boston" region="east">
            <mx:object state="AZ" city="Phoenix" region="west">
            <mx:object state="OR" city="Salem" region="west">
            <mx:object state="FL" city="Tallahassee" region="east">
            <mx:object state="MN" city="Saint Paul" region="east">
            <mx:object state="NY" city="Albany" region="east">
        </mx:object>
    </mx:object>

    <mx:togglebuttonbar id="tbb" horizontalgap="5" itemclick="filterAC(event);">
            <mx:dataprovider>
                <mx:array>
                    <mx:string>all</mx:string>
                    <mx:string>east</mx:string>
                    <mx:string>west</mx:string>
                </mx:array>
            </mx:dataprovider>
        </mx:togglebuttonbar>

    <mx:datagrid id="dg" width="100%" height="100%" rowcount="5" dataprovider="{myAC}">
        <mx:columns>
            <mx:datagridcolumn datafield="state" headertext="State">
            <mx:datagridcolumn datafield="city" headertext="City">
            <mx:datagridcolumn datafield="region" headertext="region">
        </mx:datagridcolumn>
    </mx:datagridcolumn>

</mx:datagridcolumn>
</mx:columns></mx:datagrid></mx:object></mx:object></mx:object></mx:object></mx:object></mx:object></mx:object></mx:array></mx:arraycollection></mx:application>

Here is the running sample:

This movie requires Flash Player 9

Browse the source of this example.
Download a zipfile containing the source to this sample.


No Comments »

October 23rd, 2007 by Kyle
Tags: , , , , ,
Posted in: Flex

I can’t count the number of times upon starting to work on a datagrid issue that I turn to the flex docs and copy the code sample at the bottom of the Datagrid API page. Then I usually search around for a simple sample of an itemRenderer that fits my needs. I decided it was high time I posted a simple sample that combined those needs into one sample and was located in an easy place for me and everyone else to find…my blog.

Here is the sample code for the app:

<mx:application xmlns:mx="http://www.adobe.com/2006/mxml">

    <mx:xmllist id="employees">
        <iployee>
            <name>Christina Coenraets</name>
<phone>555-219-2270</phone>
            <iail>ccoenraets@fictitious.com</iail>
            <active>true</active>
        </iployee>
        <iployee>
            <name>Joanne Wall</name>
<phone>555-219-2012</phone>
            <iail>jwall@fictitious.com</iail>
            <active>true</active>
        </iployee>
        <iployee>
            <name>Maurice Smith</name>
<phone>555-219-2012</phone>
            <iail>maurice@fictitious.com</iail>
            <active>false</active>
        </iployee>
        <iployee>
            <name>Mary Jones</name>
<phone>555-219-2000</phone>
            <iail>mjones@fictitious.com</iail>
            <active>true</active>
        </iployee>
    </mx:xmllist>      

    <mx:datagrid dataprovider="{employees}" width="600" height="400" editable="true">
        <mx:columns>
            <mx:datagridcolumn headertext="Name" datafield="name">
            <mx:datagridcolumn headertext="Phone" datafield="phone">
            <mx:datagridcolumn headertext="Email" datafield="email" itemrenderer="EmailRenderer">
        </mx:datagridcolumn>
    </mx:datagridcolumn>

</mx:datagridcolumn>
</mx:columns></mx:datagrid></mx:application>

Here is the code for the itemrenderer:

<mx:label xmlns:mx="http://www.adobe.com/2006/mxml">
    width="100%" height="100%" paddingLeft="3"
    fontWeight="{currentWeight}" fontStyle="{currentStyle}" >

    <mx:script>
        <!–[CDATA[

            import mx.controls.dataGridClasses.DataGridListData;
            import mx.controls.listClasses.BaseListData;
            import mx.events.FlexEvent;

            private var _listData:DataGridListData;
            [Bindable]–>           private var currentWeight:String = "normal";
            [Bindable]
            private var currentStyle:String = "normal";

            [Bindable]
            override public function set data(value:Object):void{
                super.data = value;
                if(data){
                    currentStyle = (data.active == "false" ? "italic" : "normal");
                }
                dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));
            }

            override public function get data():Object {
                return super.data;
            }

            [Bindable("dataChange")]
            override public function get listData():BaseListData
            {
                return _listData;
            }

            override public function set listData(value:BaseListData):void
            {
                _listData = DataGridListData(value);
                text=_listData.label;
                currentWeight = _listData.label == "ccoenraets@fictitious.com" ? "bold" : "normal";
                if(data){
                    currentStyle = (data.active == "false" ? "italic" : "normal");
                }
            }
        ]]>
    </mx:script>
</mx:label>

Here is the running app:

This movie requires Flash Player 9

Browse the source of this example.
Download a zipfile containing the source to this sample.


No Comments »

This post is to carry on from my previous post regarding moving data from ColdFusion CFCs to Flex 2 Applications Using Webservices.

Here is the first sample showing basic retrieval of a string via Remote Object:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" >
    <mx:Script>
        <![CDATA[
            import mx.rpc.events.ResultEvent;
            import mx.controls.Alert;
           
            [Bindable]
            public var sResult:String;
           
            public function handleStringResult(event:ResultEvent):void{
                sResult=event.result as String
            }
         
        ]]>
    </mx:Script>
       
    <mx:RemoteObject
        id="myService"
        destination="ColdFusion"
        source="services.HelloWorld">  
        <mx:method name="sayHelloString" result="handleStringResult(event)"  fault="Alert.show(event.fault.message)" />
    </mx:RemoteObject>

    <mx:Label id="lblStringResult" text="{sResult}"/>   
    <mx:Button label="get String Remote Object" click="myService.sayHelloString()"/>

</mx:Application>
 

This movie requires Flash Player 9

Browse the source of this example.
Download a zipfile containing the source to this sample.

Read the rest of this post»


No Comments »

One of my first blog posts pointed to a dev center article that I wrote on this topic for the Flex 2 release. I often send customers to look at this article when appropriate as it is a good starting point for webservice and remoteobject communication between Flex and Coldfusion. I also find myself referring to this sample once in a while and so I have finally decided to host the sample and cfc from my website/blog and potentially enhance the cfc to support more use cases for subsequent blog posts.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" >
    <mx:Script>
        <![CDATA[
            import mx.rpc.events.ResultEvent;
            import mx.controls.Alert;
           
            [Bindable]
            public var sResult:String;
               
            public function handleStringResult(event:ResultEvent):void{
                sResult=event.result as String
            }
           
        ]]>
    </mx:Script>
       
    <mx:WebService id="myService"
        useProxy="false"
        wsdl="http://739saintlouis.com/services/HelloWorld.cfc?wsdl"
        showBusyCursor="true">     
        <mx:operation name="sayHelloString" result="handleStringResult(event)" fault="Alert.show(event.fault.message)"/>
    </mx:WebService>
    <mx:Label id="lblStringResult" text="{sResult}"/>   
    <mx:Button label="get String via Webservice" click="myService.sayHelloString.send()"/>

</mx:Application>
 

This movie requires Flash Player 9

Browse the source of this example.
Download a zipfile containing the source to this sample.

Read the rest of this post»


2 Comments »

« Previous Entries