views:

1948

answers:

9

I have a ComboBox that I bind to a standard HTTPService, I would like to add an event listener so that I can run some code after the ComboBox is populated from the data provider.

How can I do this?

A: 

You can use BindingUtils to get notified when the dataProvider property of the combo box changes:

BindingUtils.bindSetter(comboBoxDataProviderChanged, comboBox, "dataProvider");

BindingUtils lives in the mx.binding.utils package.

I have a longer description of how to work with BindingUtils here: Does painless programmatic data binding exist?

Theo
A: 

You can also listen for the ResultEvent.RESULT on the HTTPService, that would be called slightly before the combo box got populated I guess, but it might be good enough.

Theo
+1  A: 

You can use a mx.binding.utils.ChangeWatcher as described here.

John
A: 

@Theo

Thanks for the suggestions, I need to ensure that the ComboBox has been populated, before the function I need to execute, I don't think your suggestions will give me that..

I have tried this (my class extends ComboBox):


this.addEventListener(FlexEvent.DATA_CHANGE,dataChange);

private function dataChange(e:FlexEvent):void
{
    // combobox has been databound
}

but the event does not seem to fire, even though the combo box is being populated...

mmattax
A: 

Where are you adding the listener compared to the loading of the data? Is it possible the data is being loaded, and the event fired, before you've added your listener?

Herms
A: 

@Herms

The listener is definitely added before the web service call, here is an example of what my code look like (I simplified lots of things...):

I have this flex component:


public class FooComboBox extends ComboBox
{
    private var service:HTTPService = null;
    public function ProjectAutoComplete()
    {
        service = new HTTPService();
        service.url = Application.application.poxmlUrl;
        service.addEventListener(FaultEvent.FAULT,serviceFault);
        service.addEventListener(ResultEvent.RESULT,resultReturned);


        this.addEventListener(FlexEvent.DATA_CHANGE,dataChange);
    }
    public function init():void
    {
        var postdata:Object = {};
        postdata["key"] = "ProjectName";
        postdata["accountId"] = Application.application.accountId
        service.send(postdata);
    }
    private function resultReturned(event:ResultEvent):void
    {
        this.dataProvider = service.lastResult.Array.Element;
        // thought I could do it here...but no luck...
    }
    private function dataChange(e:FlexEvent):void
    {
        // combobox has been databound
        mx.controls.Alert.show("databound!");
    }
    ...
}

and then in a mxml file I have the FooComboBox with id "foo" and I call:


foo.init();

I need to execute some code after the combobox is completely databound...any ideas?

mmattax
A: 

Maybe the event doesn't trigger when the data provider is first set? Try setting the data provider to an empty array in the constructor, so that it's definitely changing instead of just being initially assigned later in your resultReturned() method. I've no clue if that will help, but it's worth a shot.

Also, you're setting the provider to lastResult.Array.Element. That looks a little suspicious to me, as the data provider should probably be an array. Granted, I have no clue what your data looks like, so what you have could very well be correct, but it's something I noticed that might be related. Maybe it should just be lastResult.Array?

Herms
A: 

In your example code, try running validateNow() in the resultReturned method. That will force the combo box to commit its properties. The thing is that even though the property is set the new value isn't used until commitProperties is run, which it will do at the earliest on the next frame, validateNow() forces it to be done at once.

Theo
A: 

Flex doesn't have a specific data-binding events in the way that say ASP .Net does. You have to watch for the dataProvider property like John says in the first answer, but not simply to the combobox or its dataProvider property. Let's say you have a setup like this:

<!-- Assume you have extracted an XMLList out of the result 
and attached it to the collection -->
<mx:HttpService id="svc" result="col.source = event.result.Project"/>
<mx:XMLListCollection id="col"/>

<mx:ComboBox id="cbProject" dataProvider="{col}"/>

Now if you set a changewatcher like this:

// Strategy 1
ChangeWatcher.watch(cbProject, "dataProvider", handler) ;

your handler will not get triggered when the data comes back. Why? Because the dataProvider itself didn't change - its underlying collection did. To trigger that, you have to do this:

// Strategy 2
ChangeWatcher.watch(cbProject, ["dataProvider", "source"], handler) ;

Now, when your collection has updated, your handler will get triggered. If you want to make it work using Strategy 1, don't set your dataProvider in MXML. Rather, handle the collectionChange event of your XMLListCollection and in AS, over-write the dataProvider of the ComboBox.

Are these exactly the same as a databound event? No, but I've used them and never had an issue. If you want to be absolutely sure your data has bound, just put a changeWatcher on the selectedItem property of your combobox and do your processing there. Just be prepared to have that event trigger multiple times and handle that appropriately.

Space Cow