Flex accessing custom component's children properties - apache-flex

Is there a way to access children's properties of a custom components from mxml and not from the actionscript.
For example, i have a component "A"
<s:Group>
<mx:UIComponent id='childA'/>
<mx:UIComponent id='childB'/>
</s:Group>
And somewhere in the application i want to do something like this
<s:HGroup>
<components:A>
/*I want to access properties of this children objects*/
<childA width="20"/>
<childB color="0xFFFFFF"/>
</components:A>
<components:A>
/*And here too*/
<childA width="60"/>
<childB color="0x000000"/>
</components:A>
</s:HGroup>

You can do this in ActionScript; but not in MXML. In ActionScript:
componentAInstance.childA.width = 20;
componentAInstance.childB.setStyle('color',0xFFFFFF);
This is what we call a horrible break in encapsulation; becahse the "parent" should not need to know about the implementation details of its children.
ComponentA should know how to size and position its own children; in this chase childA and childB. It should not need help from ComponentA's parent.
You may find benefit in reading this blog post about how component's should communicate with each other.

Related

adding a scroller around a component tag

i have a group tag as given below but i am getting the error:'Scalar value nodes may not be state-specific'
<s:Group includeIn="newTask,branchingGroup,model_chain,model,condition">
<components:NewTask id="taskId" includeIn="newTask"/>
<components:NewBranchingGroup id="branchId" includeIn="branchingGroup"/>
<components:NewModelChain id="modelId" includeIn="model_chain" width="100%"/>
<components:Condition id="conditionId" includeIn="condition"/>
<s:Scroller>
<components:NewModel id="modelNId" includeIn="model" width="100%"/>
</s:Scroller>
</s:Group>
actually, i got this error as a result of trying to add a scroller component around the last components tag. Is there anyway i could avoid this error?
You have probably already solve this by now but I will answer it for future reference.
You are not allowed to have a state-specific (includeIn) element inside the scroller. I recommend moving the includeIn to the scroller instead.
<s:Scroller includeIn="model">
<components:NewModel id="modelNId" width="100%"/>
</s:Scroller>

Checkbox does not display properly in Flex

I have a checkbox that does not render as a checkbox and would be displayed as something similar to a button. However, it behaves like a checkbox where I can select it and the handler works with the firing event.
Here is my checkbox. I also tried it outside the or , but it has the same behavior. There is no CSS related to checkbox or the part that I am working on. I am using Flex 4.5 though.
1- Has anybody encounter such a problem?
2- Is there any way to enforce the layout inside a container and item renderer?
<mx:HBox>
<mx:CheckBox id="Test"
label="Label"
fontWeight="bold"
change="Test_changeHandler(event)"/>
</mx:HBox>
If you're using Flex 4.5, why are you using Flex 3 components? Change this to spark components and everything should be much better:
<s:HGroup>
<s:CheckBox id="Test"
label="Label"
fontWeight="bold"
change="Test_changeHandler(event)"/>
</s:HGroup>
mx:CheckBox extends mx:Button, so if you put added css that skinned mx:Button, mx:CheckBox would also get it. It's a shortcoming of flex 3 skinning. You can workaround by explicitly setting the mx:CheckBox skin.
Edit: try this
<mx:HBox>
<mx:CheckBox id="Test"
label="Label"
fontWeight="bold"
skin="{mx.skins.spark.CheckBoxSkin}"
change="Test_changeHandler(event)"
/>
</mx:HBox>
This happend to me also. Fix was to use a mx:Container as parent instead of FlexGlobals.application on the popup component.
for the second question:
I had exactly the same problem and i forced it to take the "original" skin with:
var skinClass:Class = mx.skins.spark.CheckBoxSkin;
theCheckBoxInstance.setStyle("skin", skinClass);
Because in my case the CheckBox was an ItemRenderer for a DataGrid, I've put it in the overridden createChildren methode right after the super call..
I have no explication why this happens. I encountered it in an old monster project where I was charged to make some changes...

mouseOver and mouseOut on changing size canvas

I am building a graphic component in MXML that has different states, each state having its own size.
I have a "normal" state and a "highlighted state", the highlighted one having a higher height.
On this components I implemented a function to be executed on each mouseOver and mouseOut to change from normal state to highlighted state and back.
My problem is, in the highlighted mode, the mouseout event is triggered according to the size of the normal state.
Here is the code:
<mx:Canvas xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:controller="com.*"
mouseOver="mouseOverHandler(event)" mouseOut="mouseOutHandler(event)"
width="230" height.Playing="40" height.Normal="21" height.Highlighted="40">
<mx:states>
<mx:State name="Normal" />
<mx:State name="Playing" />
<mx:State name="Highlighted" />
</mx:states>
<mx:Button includeIn="Highlighted" left="19" bottom="2" width="15" height="15" />
</mx:Canvas>
Is there something wrong in the way I use mouseOuver and mouseOut ?
Thanks,
Alexandre
I am building a graphic component in
MXML that has different states, each
state having its own size.
You have a misunderstanding of how the Flex Component Architecture works. A component never sizes itself. It is always up to the parent to size it's children. You can override the measure method to set measuredWidth and measuredHeight; however these are only suggestions provided to the component's parent. It is up the component to decide whether to accept them or no.
So, in your example, you can change the height/width of the button (a child); but you cannot change the height/width of the canvas (The component you're extending) and expect it to stick.
Without seeing the code that contains this canvas component, it's hard to say for sure what is going on. But, in this case, you should override the measure method to change the measuredWidth / measuredHeight. Something like this:
override protected measure():void{
if(currentState=='Normal'){
measuredWidth = 0;
measuredHeight = 0;
} else {
measuredWidth = button.width;
measuredHeight = button.height;
}
}
When the state changes, be sure to call the invalidateSize() method. You can do this by listening to the currentStateChange event.
In theory, that will cause the component to change the measuredWidth/measuredHeight; which will force the parent to also redraw itself, accommodating for the new measuredWidth/measuredHeight.
MXML masks a lot of these details.

BorderContainer Skin File is somehow empty

When i generate skin files lets suppose for s:Button, they contain all the design related code such as graphic, label etc, but when i create a skin file of BorderContainer, it gets created without any design code and event the contentGroup part is commented and i dont know how to use it.
Could you please guide me how to custimize its skin file?
<?xml version="1.0" encoding="utf-8"?>
[HostComponent("spark.components.BorderContainer")]
<!-- states -->
<s:states>
<s:State name="disabled" />
<s:State name="normal" />
</s:states>
<!-- SkinParts
name=contentGroup, type=spark.components.Group, required=false
-->
This should explain it better... From Abobe's Docs.... "Note: Because you use CSS styles and class properties to control the appearance of the BorderContainer container, you typically do not create a custom skin for it. If you do create a custom skin, your skin class should apply any styles to control the appearance of the container." http://help.adobe.com/en_US/flex/using/WS03d33b8076db57b9466e6a52123e854e5d5-8000.html
Also...
I've noticed if you are using the wizard under file--> new MXML Skin you will not see the BorderContainerSkin available. What you are doing is actually creating an MXML class that is derived from BorderContainer (a component class, not a skin class), therefor it does not have any of the graphics and drawing methods. It seems as if you are trying to create the wrong type of class.
Unlike most skins in Flex 4, the BorderContainerSkin class is actually an Actionscript class. So.... couple of options...
1) You Can Extend BorderContainerSkin
goto: File-->New-->Actionscript Class--> type BorderContainerSkin in the SuperClass field and select it when it appears, name your new skin class and you should be good to go.
2) Create your own
BorderContainerSkin extends Skin so You can reference the code in BoderContainerSkin and create your own actionscript class that extends Skin with your custom logic.
Hope this help
Add the skin elements into the component
then at the bottom add this line:
<s:Group id="contentGroup" left="0" top="0" right="0" bottom="0"/>
this will create a group on top of the skin.
After doing this it should act as a traditional border container.

MXML composite container initialization error

I'm getting an odd error from my composite canvas component:
An ActionScript error has occurred:
Error: null
at mx.core::Container/initialize()[C:\autobuild\galaga\frameworks\projects\framework\src\mx\core\Container.as:2560]
at -REMOVED THIS FOR STACK OVERFLOW-.view::EditableCanvas/initialize()[.../view/EditableCanvas
....
It seems to be related to the fact that my composite component has a child and I'm trying to add one in the place I'm using the component. So how can I do this correctly?
Component code looks like this (EditableCanvas.mxml):
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<mx:Image id="editTextImage"
source="#Embed('/../assets/icons/small/edit.png')"/>
</mx:Canvas>
The code that is using the code looks like this:
<view:EditableCanvas
width="290"
height="120"
backgroundColor="#FFFFFF"
horizontalScrollPolicy="off"
borderStyle="solid"
cornerRadius="3">
<mx:Text id="textContentBox" width="270" fontFamily="nautics" fontSize="12" text="{_text}"/>
</view:EditableCanvas>
So I found the solution all by my own from Adobe Flex 3 Help:
If you include child tags of the root container tag in an MXML component file, you cannot add child tags when you use the component as a custom tag in another MXML file. If you define an empty container in an MXML file, you can add child tags when you use the component as a custom tag.
The way to have child elements in a composite component (that also accepts childs from custom tag) is to add them after creationComplete in as3.
Have you tried not binding to the init() function, and instead just having creationComplete="init()" ?

Resources