1
votes

I want to give states to elements of an application, preferably without creating components for everything under the sun.

I've included an example here which attempts this (application has two states; two BorderContainers represent those two, and within those BorderContainers, I'd like to have multiple controllable states).

I'm getting errors like:

Component cannot be realized within state 'a1b1' because an ancestor is excluded from 'a1b1'.

and

Initializer for property 'states' is not allowed here

Code included below.

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" applicationDPI="160"
               xmlns:mx="library://ns.adobe.com/flex/mx"
               currentState="a1"
               >
    <s:states>
        <s:State name="a1" />
        <s:State name="a2" />
    </s:states>

    <s:BorderContainer includeIn="a1" top="100" height="60" currentState="a1b1" id="a1c">
        <s:states>
            <s:State name="a1b1" />
            <s:State name="a1b2" />
        </s:states>
        <s:Button includeIn="a1b1" label="s1b1" fontSize="16" height="35" right="10" top="10" />
        <s:Button includeIn="a1b2" label="s1b2" fontSize="16" height="35" right="10" top="30" />
    </s:BorderContainer>

    <s:BorderContainer includeIn="a2" top="150" height="60" currentState="a2b1" id="a2c">
        <s:states>
            <s:State name="a2b1" />
            <s:State name="a2b2" />
        </s:states>
        <s:Button includeIn="a2b1" label="s2b1" fontSize="16" height="35" right="10" top="10" />
        <s:Button includeIn="a2b2" label="s2b2" fontSize="16" height="35" right="10" top="30" />
    </s:BorderContainer>
    <s:Button label="s1" fontSize="16" height="35" right="10" top="10" click="currentState='a1';"/>
    <s:Button label="s2" fontSize="16" height="35" right="10" top="50" click="currentState='a2';"/>
</s:Application>

Am I just trying to get flex to do something it doesn't do? Suggestions for best practices to achieve something similar are helpful, but anything that can tell me how to just force this to work, ideal or no, would be better.

Thanks!

1

1 Answers

1
votes

The best practices is to create a reusable custom component based on spark BorderContainer.

Now for the 1st error :

Component cannot be realized within state 'a1b1' because an ancestor is excluded from 'a1b1'.

this is because a1c BorderContainer have a currentState="a1b1" but included in another state includeIn="a1" .

The second error :

Initializer for property 'states' is not allowed here

you cannot define a states array in declared component like this

<s:states>
    <s:State name="a1b1" />
    <s:State name="a1b2" />
</s:states>

it's like creating a new class property in one of his instances.

So, the best way for you is to do something like this :

A custom BorderContainer component : CustomBorderContainer.mxml

<?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="400" height="300">
    <fx:Declarations>
        <!-- Place non-visual elements (e.g., services, value objects) here -->
    </fx:Declarations>
        <s:states>
            <s:State name="a1b1" />
            <s:State name="a1b2" />
        </s:states>

    <s:Button includeIn="a1b1" label="s1b1" fontSize="16" height="35" right="10" top="10" />
    <s:Button includeIn="a1b2" label="s1b2" fontSize="16" height="35" right="10" top="30" />

</s:BorderContainer>

and use it like this :

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" applicationDPI="160"
               xmlns:mx="library://ns.adobe.com/flex/mx"
               xmlns:local="*"
               currentState="a1" >
    <s:states>
        <s:State name="a1" />
        <s:State name="a2" />
    </s:states>

    <local:CustomBorderContainer includeIn="a1" top="100" id="a1c" />
    <local:CustomBorderContainer includeIn="a2" top="150" id="a2c" />

    <s:Button label="s1" fontSize="16" height="35" right="10" top="10" click="currentState='a1';"/>
    <s:Button label="s2" fontSize="16" height="35" right="10" top="50" click="currentState='a2';"/>
</s:Application>

final result look like this :

enter image description here