DataBindings will not be able to detect assignments - actionscript-3

I have a custom component that extends WindowedApplication and a spark skin to go with it. In the skin I have an HGroup, and I would like the x position of the HGroup to be set to the right edge of the window's title. My problem is that every time I try to bind the x of the Hgroup, FlashBuilder tells me that the databinding will not be able to detect the assignemnts. Below are some of the different methods I've tried and what exactly FlashBuilder has told me:
<s:HGroup x= "{hostComponent.titleBar.titleText.right as Number}">
DataBindings will not be able to detect assignments to "right".
DataBindings will not be able to detect assignments to "titleBar".
DataBindings will not be able to detect assignments to "titleText".
<fx:Script>
<![CDATA[
private var _offset:Object;
public function get offset():Object{
return _offset;
}
public function set offset(value:Object):void{
_offset = value;
}
]]>
</fx:Script>
<fx:Binding source="hostComponent.titleBar.titleText.right" destination="offset"/>
<s:HGroup x= "{offset as Number}">
DataBindings will not be able to detect assignments to "offset".
DataBindings will not be able to detect assignments to "right".
DataBindings will not be able to detect assignments to "titleBar".
DataBindings will not be able to detect assignments to "titleText".
I'm fairly new to flex, so sorry if there is an obvious answer that I missed. Any help would be greatly appreciated.

1- verify that your skin host component is setted correctly : [HostComponent("YourComponent")]
2- create a global bindable number var and set it's value to titleBar.titleText.right
something like this :
[Bindable]public var textRightPos:Number = titleBar.titleText.right;
3- if the probleme persiste you can try to set your HGroup x value on a creationcomplete event handler
of your skin.

In the code snippent that you've provided add a metadata tag [Bindable] before '_offset'.
It should be like this:
[Bindable]
private var _offset:Object;
after this change, you'll not see any warning and databinding should work.
Also i would advice setting some default value to _offset.

Related

Flex 4.6 setting selectedChild= with a bound Variable from a Component

I'm getting the following error:
1067: Implicit coercion of a value of type String to an unrelated type mx.core:INavigatorContent.
Which is located in my main application at the line where I set the selectedChild=
Here's my code for my viewstack which is in my main application:
<mx:ViewStack id="mainViewStack"
width="100%" height="100%"
selectedChild="{topViewControlComponent.selectedChild}">
My component contains the following:
[Bindable]
public var selectedChild:String;
protected function changeView2(child:String):void
{
this.selectedChild = child;
}
<s:Button styleName="controlBarButton"
label="Events"
click="changeView2('userEvents');"/>
I got this to work when I set the viewstack navigator content base off of selectIndex and using an integer...worked fine. But I would rather call them by the id of the Navigator content so that they don't have to be in specific order, if this is possible. Or maybe there's a better way to go about this...Thanks for any help!
The selectedChild property on the ViewStack takes an actual view as its argument, not the name of a view. Using selectedIndex with an int will work fine, or you could call a function in your main application that maps between id and view instance.
Edit: As you said in the comments, you can use click="mainViewStack.selectedChild=userEvents" to set the view as desired.
However, your code in the question is acting like this:
click="mainViewStack.selectedChild='userEvents'"

if we can access outer function from rendered item by using "outerdocument" object then cant we access inner function from outside.?

These are the scripts under same application first one is under application and second is under dataGrid. from first script through outerClick() i am accessing a inner() function in itemrenderer. Well I can easily access the function outer() from innerClick() by outerDocument object but what_to_use to access inner() function in itemrenderer from outerClick() function. i tried with mx:component id"" and also class="" but it is not able to identify functions under itemrenderer.
<mx:Script>
<![CDATA[
public function outer():void{
Alert.show("Hi i am outer object");
}
public function outerClick():void{
what_to_use.inner();
}
]]>
</mx:Script>
This below item is rendered under data grid.
<s:itemRenderer>
<mx:Component>
<s:GridItemRenderer>
<fx:Script>
<![CDATA[
public function innerClick():void{
outerDocument.outer();
}
public function inner():void{
Alert.show("Hi i am inner");
}
]]>
</fx:Script>
<s:CheckBox id="sel" selected="{data.checked=sel.selected}" change="{data.checked}" click="innerClick()"/>
</s:GridItemRenderer>
</mx:Component>
</s:itemRenderer>
if we can access outer function from rendered item by using
“outerdocument” object then cant we access inner function from
outside.?
You seem to have a distinct misunderstanding of what itemRenderers are. An itemRenderer is a component definition, sort of like creating your own class. since you are using your the 'outerDocument' reference, you are creating your own class in-line / embedded within another class.
An instance of your custom itemRenderer class is created for every visible item in your List based class; so your own class is created multiple times, which means there is more than 1 instance of your itemRenderer function. How would Flex know which itemRenderer instances you want to call the function on? In fact it can't.
That is why you can call up, but you cannot call down.
If you need to make changes inside the itemRenderer, you should do so by changing the data elements of the dataProvider.
For all intents and purposes, I recommend against using outerDocument too. It is a break in encapsulation. A component should never try to access its' parent; because that often introduces an unneeded dependency to your component, limiting reuse. The proper way to "communicate up" is to dispatch an event from the itemRenderer and listen for it in the parent class.
This concept is covered briefly on the answer to one of your previous questions.

Flex How to change button state in actionscript?

i can do this:
<s:Button id="Btn" enabled.State1="false" />
But the following code is giving me an error.
private function enableDisable():void{
Btn.enabled.State1="false"; //Error: Access of undefined property State1
}
how to code enabled.State1 in ActionScript?
Thanks
I know this is not what you want to hear, but here it goes anyway: why do you want to do that? The whole purpose of the states is that you wouldn't have to write tons of ActionScript to do the same thing.
Why you can't do it like that
By writing Btn.enabled.State1 in ActionScript you're essentially saying: give me the property called 'State1' of the Boolean instance called 'enabled'. Obviously that won't work because a Boolean doesn't have such a property. You're confusing the MXML dot (.) notation - used for assigning values to properties based on states - with the ActionScript dot notation - used for reading/writing properties.
A solution or as close as it gets
Since it's the very nature of this feature that you would use it in MXML, you can't do exactly what you're asking for in ActionScript. The next best thing would be to listen for StateChangeEvent en set the Button's 'enabled' property according to the new state name.
addEventListener(StateChangeEvent.CURRENT_STATE_CHANGE, onStateChange);
private function onStateChange(event:StateChangeEvent):void {
switch (event.newState) {
case "wrong": Btn.enabled = false; break;
case "correct": Btn.enabled = true; break;
}
}
(I'm using the same states as in James' answer)
I think you may be using states in the wrong context. For instance, you have component which contains a user input with a button next to it. The button is only enabled when the correct word is input. You would define two states for the component, perhaps correct and wrong.
<s:states>
<s:State name="wrong" />
<s:State name="correct" />
<s:states>
You would then, similar to what you've done above, set individual properties for the buttons depending on the state:
<s:Button id="Btn" enabled.wrong="false" enabled.correct="true" />
By default, the state of the component would be wrong. After handling user input and checking if the correct word is entered, the state of the component would be changed to correct.
Normally the state-specific properties of components are set at compile time and the state of the component itself changed at runtime.
Here is an overview of states in Flex 4.6

In flex4 & as3 how do you change the button label dynamically?

Is there any way to change Spark button label dynamically? When i click on it, i want the label to change. I bind the String to label and gives value for the first time, but even flashBuilder shows me that Data binding will not be able to detect assignments.
Here is my button:
<s:Button name="button" label="{butt}" x="5" y="3" useHandCursor="true"
click="start()" buttonMode="true" cornerRadius="5"
skinClass="skins.CustomButtom"/>
And here is assigment:
public var butt:String = "Start";
Update
Both answers work.
Make the variable Bindable like this:
[Bindable]
public var butt:String = "Start";
It is not advisable to have buttons with changing labels.
Even if you must, it is preferable to change the label property directly instead of introducing a binding because Flash Player needs to instantiate extra listeners for bound variables.
In this case, a binding is required only if you are going to be changing the label frequently.
Without the bindable, you might have noticed that Flash will assign the value "Start" to the label of the button (generally, the value of the bound variable at the time of creation of the button).

Bindable property change event in Flex

Can anyone please help me solve this mystery:
I've got a component called Box.as that has following two properties, and have their getters & setters defined:
private var _busy:Boolean;
private var _errorMessage:String;
In MXML that uses this component I define it like this:
<components:Box skinClass="skins.components.BoxSkin"
busy="{presenter.boxBusy}"
errorMessage="{presenter.boxErrorMessage}"/>
Where presenter variable is defined here in MXML and a Presenter class has boxBusy and boxErrorMessage variables defined as bindable property change events:
[Bindable(event="propertyChange")]
function get boxBusy():Boolean;
function set boxBusy(value:Boolean):void;
[Bindable(event="propertyChange")]
function get boxErrorMessage():String;
function set boxErrorMessage(value:String):void;
PROBLEM is that whenever I change boxErrorMessage for the presenter, I see the affect in MXML but nothing happens at all when I change boxBusy. Is there something extra I need to do with boolean variable?
Thanks a lot in advance.
You should omit the (event="propertyChange") specification from your [Bindable] metadata tags on both boxBusy and boxErrorMessage. Also, make sure your get/set methods are declared public.
So, the property, boxBusy, would look something like this:
[Bindable]
public function get boxBusy():Boolean { return _busy; }
public function set boxBusy(value:Boolean):void { _busy = value; }
When you qualify [Bindable] with (event="..."), you're telling Flex, "I will dispatch the named event whenever the binding should be updated".
If you omit the event specification, then flex assumes that the event is named propertyChange. But that's not all it does. It also automatically "wraps" your setter with generated code that transparently dispatches a 'propertyChange' event any time the setter is used to modify the value. This is described in more detail here, at adobe livedocs.
So... by explicitly specifying (event="propertyChange"), you disable flex's default behavior. Even though you're using the default event name, flex will not generate the wrapper code -- instead, it will expect you to dispatch the event from your code, at the appropriate time.
I imagine that your boxErrorMessage property appears to be working, because some other [Bindable] property of your class is changing in the same pass -- thus dispatching propertyChange, and causing your boxErrorMessage binding to update as a side-effect.
It is completely possible that if you are setting busyBox to true the first time the setter is getting called but it will not get called again if you again try to set to true. The code that is by the flex compiler when you use the [Bindable] tag will adds a check to see if you are setting the new value to what the getter will currently will return. If that is the cause it isn't called.
If you were to oscillate between true and false it would get called every time because the new value differs from the current value. But setting it to true-true-true-true-false would only result in it getting called the first time to set to your and the last time to set to false.