1. #1
    Ext User
    Join Date
    Aug 2007
    Posts
    12
    Vote Rating
    0
    cristi_vladan is on a distinguished road

      0  

    Default Multiple fields sort

    Multiple fields sort


    I saw multiple opened threads, discussions talking about Ext.data.Store support for multiple fields sort and i didn't saw any valid solution, here is my solution:
    Code:
    Ext.override(Ext.data.Store, {
    		
        sortData : function(f, direction){
            direction = direction || 'ASC';
            var st = this.fields.get(f).sortType;
         	var multipleSortInfo = this.fields.get(f).multipleSortInfo;
    
            var fn = function(r1, r2){
                var v1 = st(r1.data[f]), v2 = st(r2.data[f]);
                var ret = v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
                	for (i = 0 ; (multipleSortInfo !== undefined && ret == 0 && i < multipleSortInfo.length); i++) {
         	        	var x1 = r1.data[multipleSortInfo[i].field], x2 = r2.data[multipleSortInfo[i].field];
                		var dir = (direction != multipleSortInfo[i].direction) ? direction.toggle("ASC", "DESC") : direction;            		
                           ret = (x1 > x2) ? 1 : ((x1 < x2) ? -1 : 0);
                           if (dir == 'DESC') ret = -ret;
    
                		
                	};
                return ret;
            };
            this.data.sort(direction, fn);
            if(this.snapshot && this.snapshot != this.data){
                this.snapshot.sort(direction, fn);
            }
        }   
    });
    You can use this feature by adding a new property to the Ext.data.Record, reader fields:

    For example if you want to add an extra field to be the second, third sort criteria, you can do by adding this property multipleSortInfo to the field when you build the reader record.
    Code:
    			rec = Ext.data.Record.create([
    				{name: 'a', type:'float'},
    				{name: 'b', type:'float'},
    				{name: 'date', type: 'date', dateFormat: 'd/m/Y', multipleSortInfo: [{field: 'b', direction:'DESC'}, {field: 'a', direction:'ASC'}]}
    			]);
    			reader = new Ext.data.JsonReader({
    				root: 'x'
    			}, rec);
    			
                            store = new Ext.data.GroupingStore({
    	    		        url: '/servlet', // you can load data here for example
    				sortInfo:{field: 'date', direction: "ASC"},
    	                        reader: reader
    			});
    So if you want to sort the store by date field, the date field will be the first sort criteria, and when there are multiple records with the same value, the second sort criteria will be b and so on ... (a, etc.).
    Direction from multipleSortInfo will be toggled, when sort will be changed in the main field.
    So, you can bind this store to a grid for example, and if you sort(click on header) by date ASC, then if there are multiple b on the same date, the b field will be first sorted DESC and so on ...

    Christian.
    Last edited by cristi_vladan; 1 Oct 2008 at 5:24 AM. Reason: a simpler way of comparison (thanks to Animal)

  2. #2
    Sencha - Ext JS Dev Team Animal's Avatar
    Join Date
    Mar 2007
    Location
    Notts/Redwood City
    Posts
    30,508
    Vote Rating
    56
    Animal has a spectacular aura about Animal has a spectacular aura about Animal has a spectacular aura about

      0  

    Default


    Or

    Code:
    Ext.override(Ext.data.Store, {
        /**
         * Sort by multiple fields in the specified order.
         * @param {Array} An Array of field sort specifications, or, if ascending
         * sort is required on all columns, an Array of field names. A field specification
         * looks like:<pre><code>
    {
        field: 'orderNumber',
        direction: 'ASC'
    }
    </code><pre>
         */
        sortByFields: function(fields) {
            
    //      Collect sort type functions,
    //      Convert string field names to field+direction spec objects.
            var st = [];
            for (var i = 0; i < fields.length; i++) {
                if (typeof fields[i] == 'string') {
                    fields[i] = {
                        field: fields[i],
                        direction: 'ASC'
                    };
                }
                st.push(this.fields.get(fields[i].field).sortType);
            }
    
            var fn = function(r1, r2) {
                var result;
                for (var i = 0; !result && i < fields.length; i++) {
                    var v1 = st[i](r1.data[fields[i].field]);
                    var v2 = st[i](r2.data[fields[i].field]);
                    result = (v1 > v2) ? 1 : ((v1 < v2) ? -1 : 0);
                    if (fields[i].direction == 'DESC') result = -result;
                }
                return result;
            };
            this.data.sort('ASC', fn);
            if(this.snapshot && this.snapshot != this.data){
                this.snapshot.sort('ASC', fn);
            }
            this.fireEvent("datachanged", this);
        }
    });

  3. #3
    Sencha User DTT_11-1983's Avatar
    Join Date
    Apr 2008
    Posts
    92
    Vote Rating
    2
    DTT_11-1983 is on a distinguished road

      0  

    Default


    Hi Animal,
    Where can I put sortByFields to my code ?
    I'm newbie. I tried put it in my Reader
    PHP Code:
    {name'column2'sortByFields: [{field'column1'direction:'DESC'}, {field'column2'direction:'ASC'}]} 
    but it does not work.
    Thanks
    Sorry for my bad English.

  4. #4
    Ext User
    Join Date
    Jul 2007
    Location
    Florida
    Posts
    9,996
    Vote Rating
    6
    mjlecomte will become famous soon enough mjlecomte will become famous soon enough

      0  

    Default


    Good work, I'm sure there will be some happy campers out there to see this.

    As constructive suggestion: What would probably be good is to add this to the header menu where you can alter the sort dynamically. Currently you can click on the header anywhere to sort the column, or if you hover over the hidden dropdown you can click on sorting options. So in those dropdowns might be some way to specify that you want to add to the sort array and if so in which direction should the sort be.

    Taking the thought even further there might be a sort submenu similar to the "columns" submenu. That submenu might be the GUI for the active sort implementation on the grid. Maybe that submenu could support drag/drop so you could alter the order of the sorted fields.

    I suppose an alternative to that complexity might be to implement a context menu or add to the existing menu a custom sort option the way excel does to implement the same (see image).


  5. #5
    Ext User
    Join Date
    Aug 2007
    Posts
    12
    Vote Rating
    0
    cristi_vladan is on a distinguished road

      0  

    Default


    Quote Originally Posted by DTT_11-1983 View Post
    Hi Animal,
    Where can I put sortByFields to my code ?
    I'm newbie. I tried put it in my Reader
    PHP Code:
    {name'column2'sortByFields: [{field'column1'direction:'DESC'}, {field'column2'direction:'ASC'}]} 
    but it does not work.
    Thanks
    Try my solution!

  6. #6
    Sencha - Ext JS Dev Team Animal's Avatar
    Join Date
    Mar 2007
    Location
    Notts/Redwood City
    Posts
    30,508
    Vote Rating
    56
    Animal has a spectacular aura about Animal has a spectacular aura about Animal has a spectacular aura about

      0  

    Default


    Quote Originally Posted by DTT_11-1983 View Post
    Hi Animal,
    Where can I put sortByFields to my code ?
    I'm newbie. I tried put it in my Reader
    PHP Code:
    {name'column2'sortByFields: [{field'column1'direction:'DESC'}, {field'column2'direction:'ASC'}]} 
    but it does not work.
    Thanks
    It's a function, you have to call it and it sorts by the fields you specify.

  7. #7
    Sencha User
    Join Date
    Oct 2007
    Location
    Norway
    Posts
    21
    Vote Rating
    0
    egs is on a distinguished road

      0  

    Default


    @Animal -- I have been looking at your sortByFields function and I'm wondering if it's possible to use this for sorting by Group Count when using a GroupingView.

    Here's a link to a thread describing the issue: http://extjs.com/forum/showthread.php?t=51306

    When using a GroupingView I can group by one field, and sort by the same or another field.
    I want to be able to group by one field and sort by the group count. Since this group count is different depending on the field I group by, I cannot use a "bogus" field to store the count.

    Any tips/advice would be greatly appreciated !

    Thanks !


    Quote Originally Posted by Animal View Post
    Or

    Code:
    Ext.override(Ext.data.Store, {
        /**
         * Sort by multiple fields in the specified order.
         * @param {Array} An Array of field sort specifications, or, if ascending
         * sort is required on all columns, an Array of field names. A field specification
         * looks like:<pre><code>
    {
        field: 'orderNumber',
        direction: 'ASC'
    }
    </code><pre>
         */
        sortByFields: function(fields) {
            
    //      Collect sort type functions,
    //      Convert string field names to field+direction spec objects.
            var st = [];
            for (var i = 0; i < fields.length; i++) {
                if (typeof fields[i] == 'string') {
                    fields[i] = {
                        field: fields[i],
                        direction: 'ASC'
                    };
                }
                st.push(this.fields.get(fields[i].field).sortType);
            }
    
            var fn = function(r1, r2) {
                var result;
                for (var i = 0; !result && i < fields.length; i++) {
                    var v1 = st[i](r1.data[fields[i].field]);
                    var v2 = st[i](r2.data[fields[i].field]);
                    result = (v1 > v2) ? 1 : ((v1 < v2) ? -1 : 0);
                    if (fields[i].direction == 'DESC') result = -result;
                }
                return result;
            };
            this.data.sort('ASC', fn);
            if(this.snapshot && this.snapshot != this.data){
                this.snapshot.sort('ASC', fn);
            }
            this.fireEvent("datachanged", this);
        }
    });

  8. #8
    Sencha - Ext JS Dev Team Animal's Avatar
    Join Date
    Mar 2007
    Location
    Notts/Redwood City
    Posts
    30,508
    Vote Rating
    56
    Animal has a spectacular aura about Animal has a spectacular aura about Animal has a spectacular aura about

      0  

    Default


    You'll have to look at the source. The GroupingStore will have to sort by the group field followed by whatever other fields you want to sort by. It should just work as long as teh group field is the first field in the sortByFields parameters.

  9. #9
    Sencha User
    Join Date
    Oct 2007
    Location
    Norway
    Posts
    21
    Vote Rating
    0
    egs is on a distinguished road

      0  

    Default


    @Animal -- You say that the GroupingStore will have to sort by the group field followed by whatever other fields I want to sort by. But, afaik the Group count is not a field. The Group count will not be the same if I Group by another field.

    Today I'm using
    Code:
    values.rs.length
    to display the Group count. Are you saying that I can use this as a field reference as well ?

    Thanks for any information !

  10. #10
    Sencha - Ext JS Dev Team Animal's Avatar
    Join Date
    Mar 2007
    Location
    Notts/Redwood City
    Posts
    30,508
    Vote Rating
    56
    Animal has a spectacular aura about Animal has a spectacular aura about Animal has a spectacular aura about

      0  

    Default


    Group "count"?

    http://extjs.com/deploy/dev/docs/?cl...ber=groupField

    The GroupingStore sorts by the groupField. This is what enables the GroupingView to collect its data.

    You need to tell it to sort by the groupField, and then the other fields.