javascript ExtJS 4 Grid 自定义列排序(文件管理器风格)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12932007/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 17:28:29  来源:igfitidea点击:

ExtJS 4 Grid custom columns sorting (file manager style)

javascriptextjsextjs4

提问by VisioN

I was about to make a basic file manager using ExtJS 4. The problem I faced now is: how to make custom sorting for grid panelwhen clicking the columns.

我正准备使用ExtJS 4制作一个基本的文件管理器。我现在面临的问题是:如何在单击列时对网格面板进行自定义排序

Imagine we have store fields:

想象一下我们有商店字段:

[
    { name: "is_dir", type: "boolean" },
    { name: "name",   type: "string"  },
    { name: "size",   type: "int"     }
]

And the data which comes from an array:

以及来自数组的数据:

[
    { is_dir: true,  name: "..",        size: 0    },
    { is_dir: false, name: "file2.txt", size: 512  },
    { is_dir: true,  name: "folder2",   size: 0    },
    { is_dir: false, name: "file3.txt", size: 1024 },
    { is_dir: true,  name: "folder1",   size: 0    },
    { is_dir: true,  name: "file1.txt", size: 1024 },
    // ...
]

The idea is to make sorting like in any file manager (e.g. Total Commander, MC, FAR, etc) so, that:

这个想法是在任何文件管理器(例如Total CommanderMCFAR等)中进行排序,以便:

  • the item with name ".." is always placed at the top
  • dirs go after ".." (if exists) in sorted order
  • files go after dirs (if exist) in sorted order
  • 名称为“..”的项目始终位于顶部
  • 目录按排序顺序在“..”(如果存在)之后
  • 文件按排序顺序放在目录(如果存在)之后

For example, the output with sorting by name and by size should be:

例如,按名称和大小排序的输出应该是:

^ Name           | Size               Name             | ^ Size
-----------------------               -------------------------
..               | 0                  ..               | 0
folder1          | 0                  folder1          | 0
folder2          | 0                  folder2          | 0
file1.txt        | 1024               file2.txt        | 512
file2.txt        | 512                file1.txt        | 1024
file3.txt        | 1024               file3.txt        | 1024

I've tried to write custom sorterFnfor store sortersproperty, however it didn't help. I believe there should be some easy solution for that.

我尝试sorterFn为商店sorters属性编写自定义,但它没有帮助。我相信应该有一些简单的解决方案。

采纳答案by VisioN

I have forked @Alexey's answerwith short sorting algorithm. Additionally, I fixed the problem with double sorting (because of this.callParent(arguments);which runs the basic sorting from the parent method). Here is the solution that works perfectly for me:

我用短排序算法分叉了@Alexey的答案。此外,我解决了双重排序的问题(因为this.callParent(arguments);它从父方法运行基本排序)。这是对我来说完美的解决方案:

sort: function(sorters) {
    sorters = sorters || { property: "name", direction: "ASC" };
    var mod = sorters.direction.toUpperCase() === "DESC" ? -1 : 1;

    this.sorters.clear();        // these lines are needed
    this.sorters.add(sorters);   // to update the column state

    this.doSort(function(a, b) {
        var a_type = a.get("is_dir"),
            b_type = b.get("is_dir"),
            a_name = a.get("name"),
            b_name = b.get("name");

        if (a_name === "..") return -1;
        if (a_type === b_type) {
            var a_prop = a.get(sorters.property),
                b_prop = b.get(sorters.property);

            if (a_prop === b_name) {
                return (a_name < b_name ? -1 : 1) * mod;
            } else {
                return (a_prop < b_prop ? -1 : 1) * mod;
            }
        } else {
            return b_type - a_type;
        }
    });
}

DEMO:http://jsfiddle.net/cvdNW/186/

演示:http : //jsfiddle.net/cvdNW/186/

回答by Alexey Solonets

You can override the sortmethod of your store:

您可以覆盖sort商店的方法:

Ext.define('My.store.FileStore', {
    extend: 'Ext.data.Store',

    sort: function () {
        this.doSort(function() {
            // Custom sorting function
            console.log(arguments);
            return Math.random() > 0.5 ? 1 : -1; // :)
        });
    }
});

UPDATE

更新

Ext.define('FileModel', {
    extend: 'Ext.data.Model',
    fields: [
        { name: "is_dir", type: "boolean" },
        { name: "name",   type: "string"  },
        { name: "size",   type: "int"     }
    ]
});

Ext.define('FileStore', {
    extend: 'Ext.data.Store',
    model: 'FileModel',
    data: [
        { is_dir: true,  name: "..",        size: 0    },
        { is_dir: false, name: "file2.txt", size: 512  },
        { is_dir: true,  name: "folder2",   size: 0    },
        { is_dir: false, name: "file3.txt", size: 1024 },
        { is_dir: true,  name: "folder1",   size: 0    },
        { is_dir: false, name: "file1.txt", size: 1024 },
    ],

    sorters: [{
        property: 'name',
        direction: 'ASC'
    }],

    sort: function(params) {
        var dir = params ? params.direction : 'ASC';
        var prop = params ? params.property : 'name';

        this.callParent(arguments); // UPDATE 2                    

        this.doSort(function(rec1, rec2) {
            var rec1sort = '';
            var rec2sort = '';

            if (rec1.get('is_dir') && rec2.get('is_dir')) {
                // both dirs
                if (rec1.get('name') == '..') {
                    return -1;
                }
                else if (rec2.get('name') == '..') {
                    return 1;
                }
                else {
                    return rec1.get('name').localeCompare(rec2.get('name')) * (dir == 'ASC' ? 1 : -1);;
                }
            }
            else if (rec1.get('is_dir') != rec2.get('is_dir')) {
                // file and dir
                if (rec1.get('is_dir')) {
                    if (rec1.get('name') == '..') {
                        return -2;
                    }
                    else {
                        return -1;
                    }
                }
                else {
                    if (rec2.get('name') == '..') {
                        return 2;
                    }
                    else {
                        return 1;
                    }
                }
            }
            else if (!rec1.get('is_dir') && !rec2.get('is_dir')) {
                // both files
                var result;
                if (typeof rec1.get(prop) == 'number') {
                    result = rec1.get(prop) - rec2.get(prop);
                    if (result == 0) {
                        result = rec1.get('name').localeCompare(rec2.get('name'));
                    }
                }
                else {
                    result = rec1.get('name').localeCompare(rec2.get('name'));
                }
                return dir == 'ASC' ? result : result * -1;
            }
        });
    }
});    

var grid = Ext.create('Ext.grid.Panel', {
    title: 'Files',
    store: Ext.create('FileStore'),
    renderTo: Ext.getBody(),
    columns: [{
        header: 'Name',
        dataIndex: 'name'
    }, {
        header: 'Size',
        dataIndex: 'size'    
    }]
});

回答by Bogdan M.

Sencha's Ext.Store contains now a new config object called

Sencha 的 Ext.Store 现在包含一个名为的新配置对象

E.g.:

例如:

Store config:

店铺配置:

   groupField: 'type', // here you can setup a the attribute of the model to group them by
   groupDir: 'DESC' // this is the direction

Model config:

模型配置:

   {
        name: 'createdByName',
        sortType: 'asUCText',
    },

Just by doing this and adding the sortType to the Models config, you are having now case insesnitive sorting on column name grouped by type

只需执行此操作并将 sortType 添加到 Models 配置中,您现在就可以对按类型分组的列名进行不区分大小写的排序