Search code examples
sortingapache-flexdatagridflex3arraycollection

Sort item numbers with dot on array collection in flex


I need to order an array of items by their item numbers on a datagrid in Flex 3.5.

I don't actually need to re-order it once it's inside the datagrid, I just need it to be sorted already on the arraycollection before sending it to the dataprovider.

My problem is that the proprety 'item_number' that I need to be sorted it's a string and it's built with the lot number and a dot, like this:

1.1, 1.2, 1.3, 2.1, 2.2, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10, 3.11

I need it to be ordered like this.

If I try to just order them by number, 3.2 is bigger than 3.11, so it wouldn't work. I need to order them first by the integer before the dot and only after it, by the integer after the dot, before moving on to the next integer before the dot

Also I have another problem. The item_number attribute is inside an object that is inside another object on my arraycollection.

To get to it I have to:

array_collection.item.item_number

So to sum it up, I need to list an array ordered by an attribute that's inside another object of the arrayitem and it's a number on a string separated by dot.

This is a simplified version of my code:

<mx:Script>
<![CDATA[       
    public function print_data_grid(array_collection):void
    {
        my_data_grid.dataProvider = array_collection
    }
]]>
</mx:Script>

<mx:DataGrid id="my_data_grid">
<mx:columns>
    <mx:DataGridColumn headerText="# Item">
        <mx:itemRenderer>
            <mx:Component>
                <mx:Label toolTip="{this.text}" text="{data.product.item_number}"/>
            </mx:Component>
        </mx:itemRenderer>
    </mx:DataGridColumn>

    <mx:DataGridColumn headerText="Item Name">
        <mx:itemRenderer>
            <mx:Component>
                <mx:Label toolTip="{this.text}" text="{data.product.name}"/>
            </mx:Component>
        </mx:itemRenderer>
    </mx:DataGridColumn>
</mx:columns>
</mx:DataGrid>

Solution

  • You can write a custom sort function. Here is an example. Please check if it fulfills your requirement.

    <?xml version="1.0"?>
    <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark"
               xmlns:mx="library://ns.adobe.com/flex/mx">
    <fx:Script>
    <![CDATA[
        import mx.collections.ArrayCollection;
        import mx.collections.Sort;
        import mx.utils.ObjectUtil;
    
        private var myArrayCollection:ArrayCollection = new ArrayCollection([
            {product: {item_number: "1.1", name: "A"}},
            {product: {item_number: "10.2", name: "Lottery"}},
            {product: {item_number: "10.11", name: "Book"}},
            {product: {item_number: "1.13", name: "DVD"}},
            {product: {item_number: "1.221", name: "Car"}},
            {product: {item_number: "1.211", name: "Mobile"}},
            {product: {item_number: "10.1111", name: "Laptop"}},
            {product: {item_number: "11.1", name: "Camera"}},
            {product: {item_number: "12.1", name: "Desktop"}},
            {product: {item_number: "144.41", name: "iPad"}},
            {product: {item_number: "14.21", name: "Tablet"}},
            {product: {item_number: "14.111", name: "Android phone"}},
            {product: {item_number: "10.1", name: "TV"}},
            {product: {item_number: "10.100", name: "Bulb"}}]);
    
        private function createCopyOfArrayCollection():ArrayCollection
        {
            var copyOfArrayCollection:ArrayCollection = new ArrayCollection();
            for(var i = 0; i < myArrayCollection.length; i++)
            {
                copyOfArrayCollection.addItem(mx.utils.ObjectUtil.copy(myArrayCollection[i]));
            }
            return copyOfArrayCollection;
        }
    
        private function onButtonClick():void {
            var copyOfArrayCollection:ArrayCollection = createCopyOfArrayCollection();
            var sort:Sort = new Sort();
            sort.compareFunction = sortFunction;
            copyOfArrayCollection.sort = sort;
            copyOfArrayCollection.refresh();
            print_data_grid(copyOfArrayCollection);
        }
    
        private function sortFunction(a:Object, b:Object, array:Array = null):int {
            //assuming all item_number contains one decimal
            var itemNumberA:String = a.product.item_number;
            var itemNumberASplitArray:Array = itemNumberA.split(".", 2);
            var itemNumberB:String = b.product.item_number;
            var itemNumberBSplitArray:Array = itemNumberB.split(".", 2);
    
            if (Number(itemNumberASplitArray[0]) == Number(itemNumberBSplitArray[0])) {
                if (Number(itemNumberASplitArray[1]) == Number(itemNumberBSplitArray[1])) {
                    return 0;
                }
                else if (Number(itemNumberASplitArray[1]) > Number(itemNumberBSplitArray[1])) {
                    return 1;
                }
                else {
                    return -1;
                }
            }
            else if (Number(itemNumberASplitArray[0]) > Number(itemNumberBSplitArray[0])) {
                return 1;
            }
            else {
                return -1;
            }
        }
    
        public function print_data_grid(array_collection):void {
            my_data_grid2.dataProvider = array_collection
        }
        ]]>
    </fx:Script>
    <mx:HBox verticalCenter="0" horizontalCenter="0">
        <mx:Panel title="Unsorted Data">
            <mx:DataGrid id="my_data_grid" dataProvider="{myArrayCollection}" height="400">
                <mx:columns>
                    <mx:DataGridColumn headerText="# Item">
                        <mx:itemRenderer>
                            <fx:Component>
                                <mx:Label toolTip="{this.text}" text="{data.product.item_number}"/>
                            </fx:Component>
                        </mx:itemRenderer>
                    </mx:DataGridColumn>
    
                    <mx:DataGridColumn headerText="Item Name">
                        <mx:itemRenderer>
                            <fx:Component>
                                <mx:Label toolTip="{this.text}" text="{data.product.name}"/>
                            </fx:Component>
                        </mx:itemRenderer>
                    </mx:DataGridColumn>
                </mx:columns>
            </mx:DataGrid>
        </mx:Panel>
    
        <mx:VBox height="100%">
            <mx:Spacer percentHeight="50"/>
            <mx:Button label=">>- Show sorted data ->>" click="{onButtonClick()}"/>
            <mx:Spacer percentHeight="50"/>
        </mx:VBox>
        <mx:Panel title="Sorted Data">
            <mx:DataGrid id="my_data_grid2" height="400">
                <mx:columns>
                    <mx:DataGridColumn headerText="# Item">
                        <mx:itemRenderer>
                            <fx:Component>
                                <mx:Label toolTip="{this.text}" text="{data.product.item_number}"/>
                            </fx:Component>
                        </mx:itemRenderer>
                    </mx:DataGridColumn>
    
                    <mx:DataGridColumn headerText="Item Name">
                        <mx:itemRenderer>
                            <fx:Component>
                                <mx:Label toolTip="{this.text}" text="{data.product.name}"/>
                            </fx:Component>
                        </mx:itemRenderer>
                    </mx:DataGridColumn>
                </mx:columns>
            </mx:DataGrid>
        </mx:Panel>
    </mx:HBox>
    
    </s:Application>
    

    enter image description here