1
votes

I have a standard combobox that dispatches a collection event when the dataprovider finishes initializing:

my_cb.addEventListener( CollectionEvent.COLLECTION_CHANGE, getMyStuff );

Then I have a custom component that also has a dataProvider. How do I get it to dispatch a collection change event when its dataprovider finishes loading?

From what I've read, I can't do it. Will dispatching a propertychangeevent work?

Thanks for any helpful tips!

UPDATE:

I have a custom component that I call 'SortingComboBox' but it is not a ComboBox at all; it extends Button and I set is dataProvider property to my arraycollection, model.product (which is an arraycollection).

And here is how I use the dataProvider in that component:

code

[Bindable] private var _dataProvider : Object;

    public function get dataProvider() : Object
    {
        return _dataProvider;
    }

    public function set dataProvider(value : Object) : void
    {
        _dataProvider = value;

    }

code

In the createChildren() method of this component, I use this:

BindingUtils.bindProperty(dropDown, "dataProvider", this, "dataProvider");

The dropDown is a custom VBox that I use to display labels.

5

5 Answers

1
votes

When you call the setter, you have to make sure

1) that you actually are changing the value with the setter. So even if you are inside the class, call this.dataProvider = foo instead of _dataProvider = foo

2) The binding will not trigger unless you actually change the value. If you trace you'll see that the setter actually calls the getter, if the values of what you pass into the setter and the getter are the same, the binding will not occur.

Your other option is to put an event on the getter, then just call it to trigger the binding.

[Bindable( "somethingChanged" )]
public function get dataProvider() : Object
{
    return _dataProvider;
}

dispatchEvent( new Event( "somethingChanged" ) );
1
votes

Make your dataprovider bindable

1
votes
[Bindable]
protected var _dataProvider:ArrayCollection ;

Data binding is something unique to ActionScript/Flex.
Among other things it will dispatch change events.
Maybe if you post your code for the custom component I can be more specific.

Actually can you explain what your goal is you are trying to achieve?
All I can tell is you are trying to make a button have a drop down.
Why?

1
votes

this is the custom component just to give you a better idea.

code package com.fidelity.primeservices.act.components.sortingcombobox { import com.fidelity.primeservices.act.events.component.ResetSortEvent; import com.fidelity.primeservices.act.events.component.SortEvent;

import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.geom.Rectangle;

import mx.binding.utils.BindingUtils;
import mx.controls.Button;
import mx.core.UIComponent;
import mx.effects.Tween;
import mx.events.FlexMouseEvent;
import mx.managers.PopUpManager;
import mx.events.PropertyChangeEvent;
import mx.events.PropertyChangeEventKind;

public class SortingComboBox extends Button
{
    private const MAX_LABEL_LENGTH : int = 400; 
    private const ELIPSES : String = "...";

    [Bindable]
    private var _dataProvider : Object;
    private var dropDown : SortingDropDown;
    private var inTween : Boolean;
    private var showingDropdown : Boolean;
    private var openCloseTween : Tween;

    public var noSelectionLabel : String = "No Filter";
    public var noSelectionData : String = "ALL"; 

    public function get dataProvider() : Object
    {
        return _dataProvider;
    }

    public function set dataProvider(value : Object) : void
    {
        _dataProvider = value;
    }

    private function collectionEvent(e : Event):void
    {
        trace(new Date(), e);   
    }


    public function SortingComboBox()
    {
        super();
        this.buttonMode = true;
        this.useHandCursor = true;

        inTween = false;
        showingDropdown = false;

        addEventListener(Event.REMOVED_FROM_STAGE, removedFromStage);
    }   

    override protected function createChildren() : void
    {
        super.createChildren();

        dropDown = new SortingDropDown();
        dropDown.width = 240;
        dropDown.maxHeight = 300;
        dropDown.visible = false;
        BindingUtils.bindProperty(dropDown, "dataProvider", this, "dataProvider");
        dropDown.styleName = "sortingDropDown";

        dropDown.addEventListener(SortEvent.CLOSE_SORT, closeDropDown);
        dropDown.addEventListener(FlexMouseEvent.MOUSE_DOWN_OUTSIDE, dropdownCheckForClose);
        dropDown.addEventListener(FlexMouseEvent.MOUSE_WHEEL_OUTSIDE, dropdownCheckForClose);

        dropDown.addEventListener(SortEvent.UPDATE_SORT, onSortUpdate); //this event bubbles
        dropDown.addEventListener(ResetSortEvent.RESET_SORT_EVENT, onSortUpdate);

        PopUpManager.addPopUp(dropDown, this);

        this.addEventListener(MouseEvent.CLICK, toggleDropDown);

        // weak reference to stage
        systemManager.addEventListener(Event.RESIZE, stageResizeHandler, false, 0, true);
    }


    private function stageResizeHandler(evt : Event) : void
    {
        showingDropdown = false;
        dropDown.visible = showingDropdown;
    }

    private function toggleDropDown(evt : MouseEvent) : void
    {
        if(!dropDown.visible)
        {
            openDropDown(evt);
        }
        else
        {
            closeDropDown(evt);
        }               
    }

    private function openDropDown(evt : MouseEvent) : void
    {
        if (dropDown.parent == null)  // was popped up then closed
        {
            PopUpManager.addPopUp(dropDown, this);
        }
        else
        {
            PopUpManager.bringToFront(dropDown);
        }

        showingDropdown = true;
        dropDown.visible = showingDropdown;
        dropDown.enabled = false;

        var point:Point = new Point(0, unscaledHeight);
        point = localToGlobal(point);
        point = dropDown.parent.globalToLocal(point);

        //if the dropdown is larger than the button and its
        //width would push it offscreen, align it to the left.
        if (dropDown.width > unscaledWidth && point.x + dropDown.width > screen.width)
        {
            point.x -= dropDown.width - unscaledWidth;
        }

        dropDown.move(point.x, point.y);            

        //run opening tween
        inTween = true;

        // Block all layout, responses from web service, and other background
        // processing until the tween finishes executing.
        UIComponent.suspendBackgroundProcessing();

        dropDown.scrollRect = new Rectangle(0, dropDown.height, dropDown.width, dropDown.height);
        openCloseTween = new Tween(this, dropDown.height, 0, 250);
    }

    private function closeDropDown(evt : Event) : void
    {
        //dropDown.visible = false;             
        showingDropdown = false;

        //run closing tween
        inTween = true;

        // Block all layout, responses from web service, and other background
        // processing until the tween finishes executing.
        UIComponent.suspendBackgroundProcessing();

        openCloseTween = new Tween(this, 0, dropDown.height, 250);
    }

    private function dropdownCheckForClose(event : MouseEvent) : void
    {
        if (event.target != dropDown)
            // the dropdown's items can dispatch a mouseDownOutside
            // event which then bubbles up to us
            return;

        if (!hitTestPoint(event.stageX, event.stageY, true))
        {
            closeDropDown(event);
        }
    }

    public function refresh():void
    {
        onSortUpdate(null);   
    }

    private function onSortUpdate(evt1 : Event) : void
    {
        //update the label          
        var dpLength : int = this.dataProvider.length;  

        var nextLabel : String = "";
        var nextData : String = "";

        for (var i : int = 0; i < dpLength; i++)
        {
            if (this.dataProvider[i].selected == true)
            {
                nextLabel += this.dataProvider[i].label + ", ";                     
                if (this.dataProvider[i].data != null)
                {
                    nextData += this.dataProvider[i].data + ", ";
                }
            }
        }

        if (nextLabel.length > 0)
        {
            // remove extra comma at end
            nextLabel = nextLabel.substr(0, nextLabel.length - 2);
        }

        if (nextData.length > 0)
        {
            nextData = nextData.substr(0, nextData.length - 2);
        }

        if (nextLabel.length > MAX_LABEL_LENGTH)
        {
            // limit label to MAX_LABEL_LENGTH  + ... REASON: tooltips with lots of characters take a long time to render
            nextLabel = nextLabel.substr(0, MAX_LABEL_LENGTH) + ELIPSES;                    
        }

        if (nextLabel.length == 0)
        {
            nextLabel = noSelectionLabel;
            //nextLabel = "No Filter";
        }

        if (nextData.length == 0)
        {
            nextData = noSelectionData;
            //nextData = "ALL";
        }

        label = nextLabel;
        data = nextData;
        toolTip = label;

        if (evt1 is SortEvent)
        {
            trace("sort event");
            var temp:Object = this.dataProvider;
            this.dataProvider = null;
            this.dataProvider = temp;
            this.refresh();
        }
        else
        {
            trace("not dispatching");
        }
    }


    public function onTweenUpdate(value:Number):void
    {
        dropDown.scrollRect = new Rectangle(0, value, dropDown.width, dropDown.height);
    }

    public function onTweenEnd(value:Number) : void
    {     
        // Clear the scrollRect here. This way if drop shadows are
        // assigned to the dropdown they show up correctly
        dropDown.scrollRect = null;

        inTween = false;
        dropDown.enabled = true;
        dropDown.visible = showingDropdown;

        UIComponent.resumeBackgroundProcessing();
    }

    private function removedFromStage(event:Event):void
    {
        if(inTween)
        {
            openCloseTween.endTween();
        }

        // Ensure we've unregistered ourselves from PopupManager, else
        // we'll be leaked.
        PopUpManager.removePopUp(dropDown);
    }
}

}

1
votes

Ok this code here

[Bindable]
private var _dataProvider : Object;

public function get dataProvider() : Object
{
   return _dataProvider;
}
public function set dataProvider(value : Object) : void
{
  _dataProvider = value;
}

is no different then

[Bindable]
public var _dataProvider : Object;

Since objects are passed by reference you are not protecting it in anyway and the setter and getter are pointless.
On the other hand you made the source _dataProvider Bindable so anytime the data changes it will dispatch a CollectionEvent.COLLECTION_CHANGE