Log In  
  Getting Started  
----------------------------------------

Resources

 

Code Behind

  • Code behind is MXML and ActionScript but combined in a new way to use the strengths of both
  • The logic is written in ActionScript and is placed in an ActionScript class definition
  • The layout is coded in an MXML component
  • They are linked together making the ActionScript class the root of the MXML component
  • Make sure any child control declarations that are in the ActionScript class are public
previous page next page

User rating?

ComboBoxCodeBehind.as

package as_components
{
    import mx.containers.HBox;
    import mx.controls.ComboBox;
    import mx.events.FlexEvent;
    import mx.events.ListEvent;
    import mx.formatters.DateFormatter;

    [Bindable]
    public class ComboBoxCodeBehind extends HBox
    {
        public var months:Array = new Array();
        public var dateformatter:DateFormatter = new DateFormatter();
        public var selectedIndex:int;
        public var days:Array;
        public var years:Array = new Array();
        public var monthsCB:ComboBox;
        public var daysCB:ComboBox;
        public var yearsCB:ComboBox;
        public var selectedIndexYear:int;
        public var selectedIndexMonth:int;
        public var selectedIndexDay:int;
      	public var thisYear:int;


        public function ComboBoxCodeBehind()
        {
            super();
            init();
            this.addEventListener(FlexEvent.CREATION_COMPLETE, creationCompleteHandler);
        }

        private function init():void{
            var i:int;
            var now:Date = new Date();

            var currentMonth:int = now.getMonth();
            var currentYear:int = now.getFullYear();
            var currentDay:int = now.getDate();

           	thisYear = currentYear;
            dateformatter.formatString = "MMMM";

            for (i=0; i<12; i++){
                now.setMonth(i);
                months[i] = dateformatter.format(now);
            }

            setYears(currentYear);
            setDays(currentMonth);

            selectedIndexMonth = currentMonth;
            selectedIndexYear = years.indexOf(currentYear);
            selectedIndexDay = days.indexOf(currentDay);
        }

        private function creationCompleteHandler(event:FlexEvent):void{
            monthsCB.addEventListener(ListEvent.CHANGE,monthsHandler);
            yearsCB.addEventListener(ListEvent.CHANGE, yearsHandler);
        }


        private function setDays(month:int):void{
            days = new Array();
            var i:int;

            if (month == 0 || month == 2 || month == 4 || month == 6 || month == 7 || month == 9 || month == 11){
                for(i=1; i<=31; i++)
                days.push(i);
            }else if (month == 3 || month == 5 || month == 8 || month == 10){
                for(i=1; i<=30; i++)
                days.push(i);
            }else if (month == 1){
               if (thisYear % 4 == 0){
                    for(i=1; i<=29; i++)
                    days.push(i);
                }else{
                    for(i=1; i<=28; i++)
                    days.push(i);
                }
            }
        }

        private function setYears(year:int):void{
            var j:int;
            for(j=1950; j<=year; j++){
                years.push(j);
            }
        }

        private function monthsHandler(event:ListEvent):void{
            setDays(event.currentTarget.selectedIndex);
            selectedIndexDay = 0;
        }

        private function yearsHandler(event:ListEvent):void{
            if (monthsCB.selectedIndex == 1){
                var selectedDay:int = daysCB.selectedIndex;
                thisYear = event.currentTarget.selectedItem as int;
                setDays(monthsCB.selectedIndex);
                selectedIndexDay = selectedDay;
            }
        }
    }
}

CodeBehindDisplay.mxml

<?xml version="1.0" encoding="utf-8"?>
<custom:ComboBoxCodeBehind
    xmlns:mx="http://www.adobe.com/2006/mxml"
    xmlns:custom="as_components.*">

    <mx:ComboBox id="monthsCB" dataProvider="{months}" selectedIndex="{selectedIndexMonth}"/>
    <mx:ComboBox id="daysCB" dataProvider="{days}" selectedIndex="{selectedIndexDay}"/>
    <mx:ComboBox id="yearsCB" dataProvider="{years}" selectedIndex="{selectedIndexYear}" />
</custom:ComboBoxCodeBehind>

CodeExample.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
    layout="vertical"
    backgroundColor="#FFFFFF"
    backgroundAlpha="0"
    xmlns:local="*">
    <mx:VBox>
        <local:CodeBehindForm />
    </mx:VBox>
</mx:Application>
  • Download a ZIP file that contains the applications in this module. To import the project into Flex Builder, select File > Import Flex Project.

Rendered Example

previous page next page

A few corrections to this example:

1.  In CodeExample.mxml, <local:CodeBehindForm /> should say <local:CodeBehindDisplay />

2.  In Quan Li's solution above, if a user selects day '31' from a month with 31 days and then changes the month dropdown to a month with only 30 days, '31' will still be incorrectly shown in the day dropdown.  An easier fix is to briefly change the day index to force a refresh on the displayed value:

        private function monthsHandler(event:ListEvent):void{
            setDays(event.currentTarget.selectedIndex);
            selectedIndexDay = 1;
            selectedIndexDay = 0;
        }

3.  A more subtle logic error in this example involves the month dropdown.  Change your computer date to 31 July 2008.  Then refresh this page and notice the month dropdown has no February month and two March months.  This is because 'now' is a date with 31 days but when now.setMonth(i) is called in the init() function, setMonth tries to set the date to February 31st (which doesn't exist) so 'now' is converted to February 29th + 2 days which equals March 2nd so 'March' appears in the dropdown for February.  To fix this, in the init() function, set 'now' to be the first day of the month:

            for (i=0; i<12; i++){
                now.setDate(1);
                now.setMonth(i);
                months[i] = dateformatter.format(now);
            } 

Subtle bug, eh?

Posted by nnnhh lloool at Jul 30, 2008 16:08Updated by nnnhh lloool

One more minor point: the previous tutorial, "Custom Components - ActionScript 3.0", indicates the following best practice for package naming convention:

"(It's best practice to use com.*.components where *=your own designator, and use components because this is an extension of an existing component.)"

Posted by nnnhh lloool at Jul 30, 2008 16:21Updated by nnnhh lloool

Here is another correction to this example

Add the else statement after the if condition in yearsHandler function

     else
            thisYear = yearsCB.selectedItem as int;

otherwise, thisYear will always be "currentYear", means 2008. it will be a problem when ur selected month is not Feb first, change to another year and then select Feb, you will find the day has 29, beaz thisYear is still 2008.

BTW, replace <local:CodeBehindDisplay /> to <local:CodeBehindDisplay id="myCalendar"/>

then you can access the value you want by myCalendar.

Leap years are not handled correctly by the example.

Years that are evenly divisible by 100 are not leap years, unless they are also evenly divisible by 400, in which case they are leap years.

So the line

 if (thisYear % 4 == 0){

 has to be changed to

if ( (thisYear % 4 == 0) && ( !(thisYear %100 == 0) || (thisYear %400 == 0) ) ){
Added by Annette Kunovic , last edited by matthew horn on Apr 22, 2008  (view change)
Labels: 
(None)

Powered by Atlassian Confluence 2.7.1, the Enterprise Wiki. Bug/feature request - Atlassian news - Contact administrators