Null in Flex ComboBox

How can you create a combobox where the user can choose null?

If you just create a combobox with nullin the dataprovider, this value appears, but the user cannot select it:

<mx:ComboBox id="cb" dataProvider="{[null, 'foo', 'bar']}" />

Is there any way to make this choice null?

The workaround is to add an element to the dataProvider, which is not null but represents "null"; and then map between zero and this object every time you access dropdown lists. But this is not a very elegant solution; you always had to consider this mapping in all the code that refers to the "nullable" combobox ...

Edit: extension on why I don't like the workaround: Of course, this can be done in a subclass, but either I introduce new attributes (for example, nullableSelectedItem); but then you have to be careful to always use these attributes. Or I redefine ComboBoxes selectedItem; but I'm afraid this will break the base class: it might not like something that changes its idea of ​​what is from the currently selected item from the inside. And even this fragile hacking works, on top of selectedItemand dataProviderthis nullItem also needs to be handled special in dataand listDatafor renderers inlabelFunctionand then it’s probably still affected by the event the ComboBox sends ... This may work, but it is enough to hack to fix the problem, if the user clicks on an element, it is not activated (for the rest, the ComboBox handles a zero penalty). (Another alternative is to have a ui component delegate for the ComboBox, but this is even much more code to avoid this small problem)

+3
source share
5 answers

The following solution is perhaps the simplest:

<mx:ComboBox id="cb" dataProvider="{[{label:"", data:null}, {label:'foo', data:'foo'}, {label:'bar', data:'bar'}]}" />

and access data using cb.selectedItem.data

However, this simple solution is not user friendly, as Wouter mentioned.

So, here is a more complex solution that allows you to select null objects :

<mx:ComboBox id="cb" dataProvider="{[null, 'foo', 'bar']}" dropdownFactory="{new ClassFactory(NullList)}" />

NullList - :

package test
{
import mx.controls.List;

public class NullList extends List
{
    public function NullList()
    {
        super();
    }

    override public function isItemSelectable(data:Object):Boolean
    {
        if (!selectable)
            return false;
        return true;
    }

}
}
+3

, - . .

dataprovider / ( arraycollections ).

package {

    import flash.events.Event;
    import flash.events.FocusEvent;
    import mx.collections.ArrayCollection;
    import mx.collections.ICollectionView;
    import mx.collections.IList;
    import mx.containers.FormItem;
    import mx.controls.ComboBox;
    import mx.events.CollectionEvent;
    import mx.events.ListEvent;
    import mx.validators.Validator;

    public class EmptyItemComboBox extends ComboBox {

        protected var _emptyItem:Object = null;
        protected var _originalDataProvider:ICollectionView = null;

        public function EmptyItemComboBox() {
            super();
            addEmptyItem();
            addEventListener(Event.CHANGE, onChange);
        }

        private function onChange(event:Event):void {
            dispatchEvent(new Event("isEmptySelectedChanged"));
        }

        [Bindable]
        public function get emptyItem():Object {
            return _emptyItem;
        }

        public function set emptyItem(value:Object):void {
            if (_emptyItem != value) {
                clearEmptyItem();
                _emptyItem = value;
                addEmptyItem();
            }
        }

        [Bindable(event="isEmptySelectedChanged")]
        public function get isEmptySelected():Boolean {
                return (selectedItem == null || (_emptyItem != null && selectedItem == _emptyItem));
        }

        override public function set selectedItem(value:Object):void {
            if (value == null && emptyItem != null) {
                super.selectedItem = emptyItem;
            } else    if (value != selectedItem) {
                super.selectedItem = value;
            }
            dispatchEvent(new Event("isEmptySelectedChanged"));
        }

        override public function set dataProvider(value:Object):void {
            if (_originalDataProvider != null) {
                _originalDataProvider.removeEventListener(
                        CollectionEvent.COLLECTION_CHANGE,
                        onOriginalCollectionChange);
            }
            super.dataProvider = value;
            _originalDataProvider = (dataProvider as ICollectionView);
            _originalDataProvider.addEventListener(
                    CollectionEvent.COLLECTION_CHANGE,
                    onOriginalCollectionChange)
            addEmptyItem();
        }

        private function clearEmptyItem():void {
            if (emptyItem != null && dataProvider != null 
                    && dataProvider is IList) {
                var dp:IList = dataProvider as IList;
                var idx:int = dp.getItemIndex(_emptyItem);
                if (idx >=0) {
                    dp.removeItemAt(idx);    
                }
            }
            dispatchEvent(new Event("isEmptySelectedChanged"));
        }

        private function addEmptyItem():void {
            if (emptyItem != null) {
                 if (dataProvider != null && dataProvider is IList) {
                    var dp:IList = dataProvider as IList;
                    var idx:int = dp.getItemIndex(_emptyItem);
                    if (idx == -1) {
                        var newDp:ArrayCollection = new ArrayCollection(dp.toArray().concat());
                        newDp.addItemAt(_emptyItem, 0);
                        super.dataProvider = newDp;
                    }
                }
            }
            dispatchEvent(new Event("isEmptySelectedChanged"));
        }

        private function onOriginalCollectionChange(event:CollectionEvent):void {
            if (_emptyItem != null) {
                dataProvider = _originalDataProvider;
                addEmptyItem();
            }
        }
    }
}

>

:

  • . : dataproviders, , Flex, , .

  • , , .

  • dataprovider, , : .

  • " " emptyItem: ( ) .

, ...

    <mx:Script>
    <![CDATA[
        import mx.controls.Alert;
    ]]>
    </mx:Script>

    <mx:ArrayCollection id="myDP">
    <mx:source>
        <mx:Array>
            <mx:Object value="1" label="First"/>  
            <mx:Object value="2" label="Second"/>
            <mx:Object value="3" label="Third"/>
        </mx:Array>
    </mx:source>
    </mx:ArrayCollection>

    <local:EmptyItemComboBox id="comboBox" dataProvider="{myDP}" labelField="label">
    <local:emptyItem>
        <mx:Object value="{null}" label="(select an item)"/>  
    </local:emptyItem>
    </local:EmptyItemComboBox>

    <mx:Button label="Show selected item" click="Alert.show(comboBox.selectedItem.value)"/>

    <mx:Button label="Clear DP" click="myDP.removeAll()"/>
    <mx:Button label="Add item to DP" click="myDP.addItem({value: '4', label: 'Fourth'})"/>
    <mx:Button label="Reset DP" click="myDP = new ArrayCollection([{value: '1', label: 'First'}])"/>

    <mx:Label text="{'comboBox.isEmptySelected = ' + comboBox.isEmptySelected}"/>

</mx:Application>

>

+5

, . , , " ", - , ComboBox DataProvider.

Super ComboBox.

+1

, - prompt = "".

This will not allow the combo box to automatically select the first item in the dataProvider, but as soon as the user selects the item, an empty line will no longer be displayed.

0
source

requireSelection = "false" allows an empty value and the prompt allows you to enter text for this empty value if you want.

0
source

Source: https://habr.com/ru/post/1709748/


All Articles