combobox dataprovider - apache-flex

I have the following:
<mx:RemoteObject id="myCFC" destination="ColdFusion" source="components.myCFC" showBusyCursor="true">
<mx:method name="getStuff" result="UserHandler(event);"/>
</mx:RemoteObject>
...
<mx:ComboBox id="propertyCode" dataProvider="{qry_stuff}" labelField="name" />
Index.as has:
[Bindable] public var qry_stuff:ArrayCollection = new ArrayCollection;
private function UserHandler(event:ResultEvent):void {
qry_stuff= event.result as ArrayCollection;
}
public function init():void {
/* call my remote Object to get my data */
myCFC.getStuff();
}
my problem is the combobox displays [object Object]
I know there is nothing wrong with the cfc and there is a field called "name" in getStuff. Why does it not display the value of the object?
thanks in advance.

There is a property on the ComboBox class called labelField. Go ahead and set that to the name field on the data that is returned. If that doesn't work - you need to debug your returned values from CF - to be sure that the name property is actually being populated on the client side as well.
In addition, you data is probably being returned as an array (not an ArrayCollection) - in which case, you would need to set:
qryStuff = ArrayCollection( event.result as Array );
Note: You probably also want to 'strong-type' your response data by creating an ActionScript value object - so that it is not just a generic 'object' that is being returned from CF. You then can use the [RemoteClass(alias="com.sample.MyCFC")] metadata tag to map that value object to your server-side VO.

In my cfc, I had to explicitly set data/label.

Related

Questions about bindable in Flex

Since I found the webpages explaning the bindable propety quite confusing,so I would like to post my question here,which is quite simple,if I declare a variable to be bindable,does that mean whenever I changed the value of this variable in another class,all appearence of this variable will be synchronized to be the same value at the same time?
Say,if boolean variable "select" is declared to be bindable in Class A and default to be false,and we have an if statement in class A like if(select).
Then in another class,we changed the value of "select" to be true,will that if(select) statement pass the test ?
Also,how about the following setter method that is defined to be bindable:
[Bindable]
public function set isShowingAvg(b:Boolean):void
{
_isShowingAvg = b;
hasChanged();
}
Does this code imply that changing the value of _isShowingAvg is also going to be broadcasted?
Thanks in advance.
Thanks for your idea.
Declaring a property as Bindable means that when you change the value, an event will get broadcasted. This event enables data binding, but it's not necessarily automatic.
If the consuming class is MXML and you use brackets, like this:
<mx:Button enabled="{selected}" />
Then the MXML compiler will generate the appropriate binding code and anytime selected changes, enabled will also get changed.
If you're using it outside MXML then you'll either subscribe to the event to detect changes or use BindingUtils.
In your example I think you need to mark the getter [Bindable] and not the setter.
example:
public static const SHOWING_AVG_CHANGED:String = "showingAvgChangedEvent";
[Bindable(event="showingAvgChangedEvent")]
public function get isShowingAvg():Boolean
{
return _isShowingAvg;
}
public function set isShowingAvg(isShowing:Boolean):void
{
_isShowingAvg = isShowing;
dispatchEvent(new Event(SHOWING_AVG_CHANGED));
}

Flex: make getter Bindable in an value object

I have an value object in Flex which looks like:
[Bindable]
public class MyVO
{
public var a:ArrayCollection;
public var b:ArrayCollection;
private var timeSort:Sort;
public function ShiftVO(){
timeSort = new Sort();
timeSort.compareFunction = sortDates;
}
public function get times():ArrayCollection{
var ac:ArrayCollection = new ArrayCollection(a.toArray().concat(b.toArray()));
ac.sort = timeSort;
ac.refresh();
return ac;
}
It's about the getter method. I display the data of the getter in a datagrid and whenever I change some values of a or b I want to update the view as well. How do I achieve this? Currently the view doesn't update itself automatically, I have to open up the view again to see the new values.
When you make a property [Bindable], the Flex will read the getter whenever its setter is called (ie, when the property is updated); you haven't declared any setter and hence there is no way for Flex to know that the value of property has been updated.
You must define both a setter and a getter method to use the [Bindable] tag with the property. If you define just a setter method, you create a write-only property that you cannot use as the source of a data-binding expression. If you define just a getter method, you create a read-only property that you can use as the source of a data-binding expression without inserting the [Bindable] metadata tag. This is similar to the way that you can use a variable, defined by using the const keyword, as the source for a data binding expression.
May be you can define an empty setter and call it whenever you update a or b.
public function set times(ac:ArrayCollection):void { }
//somewhere else in the code:
a = someArrayCol;
/**
* this will invoke the setter which will in turn
* invoke the bindable getter and update the values
* */
times = null;
Just noticed that you're using Bindable on the class instead of the property: when you use the Bindable tag this way, it makes
usable as the source of a binding expression all public properties that you defined as variables, and all public properties that are defined by using both a setter and a getter method.
Thus, unless you define a setter, the property is not bindable even if the whole class is declared as bindable.

Having trouble with binding

I'm not sure if I'm misunderstanding the binding in Flex. I'm using Cairngorm framework. I have the following component with code like:
[Bindable]
var _model:LalModelLocator = LalModelLocator.getInstance();
....
<s:DataGroup dataProvider="{_model.friendsSearchResults}"
includeIn="find"
itemRenderer="com.lal.renderers.SingleFriendDisplayRenderer">
<s:layout>
<s:TileLayout orientation="columns" requestedColumnCount="2" />
</s:layout> </s:DataGroup>
in the model locator:
[Bindable]
public var friendsSearchResults:ArrayCollection = new ArrayCollection();
Inside the item renderer there is a button that calls a command and inside the command results there is a line like this:
model.friendsSearchResults = friendsSearchResults;
Putting break points and stepping through the code I confirmed that this like gets called and the friendsSearchResults gets updated.
To my understanding if I update a bindable variable it should automatically re-render the s:DataGroup which has a dataProvider of that variable.
There's nothing obviously wrong in the code sample. It should work so I think there's a problem elsewhere.
I would recommend setting a breakpoint where the dataProvider is assigned and also where model.friendsSearchResults is assigned. Make sure they're both pointing to the same object instance. Then step through the property assignment and corresponding event.
To make debugging easier you can switch to using a named event instead of the default. With a named event, only event listeners interested in your particular property are triggered instead of any listeners listening for any property change. This is easier to debug and will run faster. For example, change:
[Bindable]
public var results:ArrayCollection;
to
[Bindable("resultsChanged")]
private var _results:ArrayCollection;
public function get results():ArrayCollection {
return _results;
}
public function set results(value:ArrayCollection):Void {
_results = value;
dispatchEvent(new Event("resultsChanged"));
}
Another thing to keep in mind is that bindings hide certain errors like null reference exceptions. They assume the value simply isn't available yet and suppress the error. Stepping through the assignment and related bindings will help find a problem like this.

Binding to a read-only getter in AS3

Consider the following code:
[Bindable(event="ReportHeaderVO_effectiveFromDateJulian_updated")]
public function set effectiveFromDateJulian ( value:Number ) : void
{
_effectiveFromDateJulian = value;
dispatchEvent( new FlexEvent("ReportHeaderVO_effectiveFromDateJulian_updated") );
}
public function get effectiveFromDateJulian () : Number
{
return _effectiveFromDateJulian;
}
public function get effectiveFromDate () : Date
{
return DateUtil.convertJDEJulianToDate(_effectiveFromDateJulian);
}
There is a setter and a getter for the effectiveFromDateJulian which is a number representation of the date. I have provided a seperate getter which retrieves the same value, only converted to a proper date. It is a getter only though and relies on the setter for the numeric property to get its data from; so the effectiveFromDate property is effectively read-only.
Data binding works on the effectiveFromDateJulian property; any updates work fine and notify everything properly. But when binding to the effectiveFromDate (getter only) property, I get a warning from the compiler:
warning: unable to bind to property 'effectiveToDate' on class 'com.vo::ReportHeaderVO'
Is there a way to make it possible to bind to this read-only property? I would assume I would have to dispatch an event on the setter that effects the read-only property, but I don't know what that would look like.
This is a simple example, you could imagine a read-only property that depends on several setters to function and when any of those setters are updated the read-only property would need to fire a propertyChanged event as well. Any ideas? Please let me know if I need to clarify anything.
Update:
From the Adobe documentation here:
http://livedocs.adobe.com/flex/3/html/help.html?content=databinding_8.html
Using read-only properties as the
source for data binding
You can automatically use a read-only
property defined by a getter method,
which means no setter method, as the
source for a data-binding expression.
Flex performs the data binding once
when the application starts.
Because the data binding from a
read-only property occurs only once at
application start up, you omit the
[Bindable] metadata tag for the
read-only property.
And this makes sense for constant values, but in this case the value does change, it just doesn't get set directly.
Make the readonly getter Bindable and dispatch the corresponding event from the original setter method.
[Bindable(event="ReportHeaderVO_effectiveFromDateJulian_updated")]
public function set effectiveFromDateJulian ( value:Number ) : void
{
_effectiveFromDateJulian = value;
dispatchEvent( new FlexEvent("ReportHeaderVO_effectiveFromDateJulian_updated") );
dispatchEvent( new FlexEvent("ReportHeaderVO_effectiveFromDate_updated") );
}
[Bindable(event="ReportHeaderVO_effectiveFromDate_updated")]
public function get effectiveFromDate (date:Date) : Date
{
return DateUtil.convertJDEJulianToDate(_effectiveFromDateJulian);
}

Bind dataprovider DataGrid to an Array

How do you bind the dataprovider of a DataGrid in Flex to an Array?
This doesn't seem to work:
<mx:DataGrid
id="valuesDataGrid"
editable="true"
width="100%"
height="100%"
dataProvider="{_metaDataKey.values}">
...
[Bindable]
public class EnumMetaDataKey{
private var _values:Array = [];
public function get values():Array { return _values; }
public function set values(value:Array):void { _values = value; }
...
Use an ArrayCollection instead. Arrays do not lend well to binding. IIRC, this is documented in the Flex 3 help on Binding to functions Objects and Arrays:
Note: When defining a data binding expression that uses an array as the source of a data binding expression, the array should be of type ArrayCollection because the ArrayCollection class dispatches an event when the array or the array elements change to trigger data binding. For example, a call to ArrayCollection.addItem(), ArrayCollection.addItemAt(), ArrayCollection.removeItem(), and ArrayCollection.removeItemAt() all trigger data binding.

Resources