Question

Here's my component's code:

<?xml version="1.0" encoding="utf-8"?>
<s:BorderContainer xmlns:fx="http://ns.adobe.com/mxml/2009"
                   xmlns:s="library://ns.adobe.com/flex/spark"
                   xmlns:mx="library://ns.adobe.com/flex/mx"
                   width="950" height="50" creationComplete="this_creationCompleteHandler(event)"
                   currentState="default" enabled="{currentBox!=null}">
    <s:states>
        <s:State name="default"/>
        <s:State name="boxSelected" stateGroups="admin"/>
        <s:State name="textBoxSelected" stateGroups="user"/>
        <s:State name="imageBoxSelected" stateGroups="user"/>
    </s:states>
    <s:layout>
        <s:HorizontalLayout gap="10" horizontalAlign="left" paddingBottom="10" paddingLeft="10"
                            paddingRight="10" paddingTop="10" verticalAlign="middle"/>
    </s:layout>

    <fx:Script>
        <![CDATA[
            import mx.events.FlexEvent;

            public var model:Model;

            private var _currentBox:Box = null;
            [Bindable]
            public function set currentBox(box:Box):void 
            {
                _currentBox = box;
                if(model.userType == Model.USER_TYPE_ADMIN)
                    currentState = "boxSelected";
                else if(box is TextBox)
                    currentState = "textBoxSelected";
                else if(box is ImageBox)
                    currentState = "imageBoxSelected";
                else
                    currentState = "default";
            }

            public function get currentBox():Box
            {
                return _currentBox;
            }

            protected function this_creationCompleteHandler(event:FlexEvent):void
            {
                AppEventBus.instance.addListener(AppEvent.BOX_SELECTED, boxSelectedHandler);
                AppEventBus.instance.addListener(AppEvent.PAGE_SELECTED, pageSelectedhandler);
            }

            protected function boxSelectedHandler(event:AppEvent):void
            {
                currentBox = event.data as Box;
            }

            protected function pageSelectedhandler(event:AppEvent):void
            {
                currentBox = null;
            }

        ]]>
    </fx:Script>
    <fx:Declarations>
        <!-- Place non-visual elements (e.g., services, value objects) here -->
    </fx:Declarations>

    <s:ToggleButton id="secureLockButton" includeIn="admin, user" width="20" height="20"
                    selected="@{currentBox.secured}"
                    styleName="secureButtonStyle"/>
    <s:DropDownList id="fontsList" includeIn="textBoxSelected" width="150" height="20"
                    selectedItem="@{(currentBox as TextBox).font}"
                    dataProvider="{(currentBox as TextBox).fonts}"/>
    <s:DropDownList id="fontSizesList" includeIn="textBoxSelected" width="60" height="20"
                    selectedItem="@{(currentBox as TextBox).fontSize}"
                    dataProvider="{(currentBox as TextBox).fontSizes}"/>
    <s:DropDownList id="boxTypes" includeIn="boxSelected" width="70" height="20"
                    dataProvider="{Box.BOX_TYPES}" selectedItem="{currentBox.boxType}"/>
    <s:TextInput id="boxName" includeIn="boxSelected" width="70" height="20"
                 text="@{currentBox.name}"/>
</s:BorderContainer>

Box class has two inheritors: TextBox and ImageBox. All of these classes are [Bindable]. In the other component I select Box object and notify about this event the component above with EventBus. I also use it to pass selected Box object. Each TextBox object has ArrayCollection of available font sizes (fonts) and a selected one. I want bind my DropDownList to these values in two ways. So DropDownList always displays currently selected font size (font) of a box and if user select another value from the list it's set into current TextBox object.

When I select TextBox object for the first time everything works fine but when I select another one I get the error:

RangeError: Property fontSize value 0 is out of range at flashx.textLayout.property::Property$/defaultErrorHandler()[C:\Vellum\branches\v2\2.0\dev\output\openSource\textLayout\src\flashx\textLayout\property\Property.as:31] at flashx.textLayout.property::Property/setHelper()[C:\Vellum\branches\v2\2.0\dev\output\openSource\textLayout\src\flashx\textLayout\property\Property.as:230] at flashx.textLayout.formats::TextLayoutFormat/setStyleByProperty()[C:\Vellum\branches\v2\2.0\dev\output\openSource\textLayout\src\flashx\textLayout\formats\TextLayoutFormat.as:628] at flashx.textLayout.formats::TextLayoutFormat/set fontSize()[C:\Vellum\branches\v2\2.0\dev\output\openSource\textLayout\src\flashx\textLayout\formats\TextLayoutFormat.as:1044] at spark.core::CSSTextLayoutFormat()[E:\dev\4.y\frameworks\projects\spark\src\spark\core\CSSTextLayoutFormat.as:75] at spark.components::RichEditableText/updateStylesIfChanged()[E:\dev\4.y\frameworks\projects\spark\src\spark\components\RichEditableText.as:3649] at spark.components::RichEditableText/commitProperties()[E:\dev\4.y\frameworks\projects\spark\src\spark\components\RichEditableText.as:2509] at mx.core::UIComponent/validateProperties()[E:\dev\4.y\frameworks\projects\framework\src\mx\core\UIComponent.as:8219] at mx.managers::LayoutManager/validateProperties()[E:\dev\4.y\frameworks\projects\framework\src\mx\managers\LayoutManager.as:597] at mx.managers::LayoutManager/doPhasedInstantiation()[E:\dev\4.y\frameworks\projects\framework\src\mx\managers\LayoutManager.as:813] at mx.managers::LayoutManager/doPhasedInstantiationCallback()[E:\dev\4.y\frameworks\projects\framework\src\mx\managers\LayoutManager.as:1180]

Somehow selectedValue property of DropDownList becomes 0. What am I doing wrong?

Was it helpful?

Solution

It's not easy to see what is happenning "under the hood" without debugging this actual app. You could trace all setters yourself to see the order in which the bindibgs occurs.

Because what could be hapenning in my opinion is that the two bindings (selectedItem and dataProvider) - are not in sync as you wish to be. You never know which one will happen first, and more importantly, what happens inside that drpdownlist when you set one of them. Result is, that in one point the two-way-binding sets back selectedItem which is null at that moment and sets 0 to fontSize (because Number(null) is 0). And that 0 results in that error which occurs somewhere else.

Just try what is acually being set in fontSize setter (put a trace() in it) for start.

You know, since two way binding seems to be nice idea, I always ended back to "classic binding" with handling change event (setting back in this event handler). We always met some problem similar to this one when using two-way bind.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top