2 Replies Latest reply on Dec 3, 2009 12:58 AM by Sebastien V.

    DataGrid Multiple column sorting (without AdvancedDataGrid)

    Sebastien V. Level 3

      Hi.

       

      I needed to implement dynamic sorting on multiple columns on a DataGrid (not an AdvancedDataGrid), and found no good solution, so I created mine. Maybe this can help some of you.

       

       

      Here is how to do that:

       

      Subclass the SDK DataGrid :

       

       

       

      public class MyDataGrid extends DataGrid {

           ...

      }

       

       

       

      Create your own event listener on the header release event, in the MyDataGrid constructor for instance :

       

       

       

      addEventListener( DataGridEvent.HEADER_RELEASE    , onHeaderRelease ,  false , int.MAX_VALUE );

       

       

       

      The int.MAX_VALUE is here to ensure that our listener will be the first one to be called.

       

      Then implement the listener :

       

       

       

      private function onHeaderRelease( event:DataGridEvent ):void {
            event.preventDefault();
            sortByColumn( event.columnIndex );
      }

       

       

       

      Don't forget to prevent the default behaviour of the event, so that our sort will be the only one used here (that's why we need our listener to be the first one called).

       

      And finally take the SDK DataGrid's header release listener and customize it :

       

       

       

              private function sortByColumn( index :int ) :void {
                  var c :DataGridColumn = columns[ index ];
                  var desc :Boolean = c.sortDescending;

       

                  // do the sort if we're allowed to
                  if ( c.sortable ) {
                      var s :Sort = collection.sort;
                      var f :SortField;
                      if ( s ) {
                          s.compareFunction = null;
                          // analyze the current sort to see what we've been given
                          var sf :Array = s.fields;
                          if ( sf ) {
                              for ( var i :int = 0 ; i < sf.length ; i++ ) {

       

                                  if ( sf[ i ].name == c.dataField ) {
                                      // we're part of the current sort
                                      f = sf[ i ]
                                      // flip the logic so desc is new desired order
                                      desc = !f.descending;
                                      break;
                                  }
                              }
                          }
                      } else
                          s = new Sort;

       

                      if ( !f )
                          f = new SortField( c.dataField );

       


                      c.sortDescending = desc;

       

                      // if you have a labelFunction you must supply a sortCompareFunction
                      f.name = c.dataField;
                      if ( c.sortCompareFunction != null ) {
                          f.compareFunction = c.sortCompareFunction;
                      } else {
                          f.compareFunction = null;
                      }
                      f.descending = desc;

                      // Avoid NullPointerException on first sort
                      if ( s.fields == null )
                          s .fields = [];
                     
                      // Add the new SortField to the collection sort
                      if ( ArrayUtil.getItemIndex( f , s.fields ) != -1 ) {
                          s.fields = ArrayUtils.removeItem( f , s.fields );
                      }
                      s.fields.unshift( f );
                  }
                  collection.sort = s;
                  collection.refresh();
              }

       

       

       

      And there you go...

       

      Almost forgot : the ArrayUtils.removeItem code :

       

       

       

              /**
               * Creates a new Array containing the same elements as the given one,
               * excepted for the given object to remove.
               */
              public static function removeItem( element:Object , array:Array ):Array {
                  var result    :Array = [];
                  for ( var i:int = 0 ; i < array.length ; i++ )
                      if ( array[i] != element )
                          result.push( array[i] );
                 
                  return result;
              }

       

       

       

      Hope this can still help some of you...