解析kendo网格过滤字符串到过滤器对象

时间:2014-09-18 06:13:40

标签: jquery kendo-ui telerik kendo-grid datasource

我已经创建了一个伪网格窗口小部件(基本上只是一个网格头),允许用户根据自己的喜好配置排序和过滤器,然后保存这些配置以供将来使用。问题是它们是作为字符串从数据库返回的。不幸的是,我需要一种将它们转换回javascript对象的方法,以便将它们应用到网格中。

我正在使用下面的parameterMap函数将DataSourceRequest对象转换为可以发布到控制器操作并保存在数据库中的对象。该函数只接受从kendoGrid.dataSource返回的对象,并将它们转换为各种查询字符串。所以,这个:

    // Get datasource of the filter grid, so we can save the search applied to it.
    var f = $("#filter-grid").data("kendoGrid").dataSource;

    // Set the filtering/sorting applied to the filter grid in the model being saved.
    e.model.Request = e.sender.dataSource.transport.parameterMap({
        filter: f.filter(),
        group: f.group(),
        page: f.page(),
        pageSize: f.pageSize(),
        sort: f.sort()
    });

返回:

    Object {
        sort: "InvoiceNumber-asc", 
        page: 1, 
        pageSize: 100, 
        group: "", 
        filter: "Auditor~startswith~'Gabe'~and~Auditor~endswith~'Newell'"
    }

是否有任何javascript函数提供Kendo UI的东西,允许将查询字符串解析为javascript对象?我基本上想要反转parameterMap()函数的结果。我的最终目标是避免将我自己的解析这些字符串的方法转换回对象,而且似乎Kendo套件中的某些东西应该为我处理这个问题。

Telerik文档确实提供了一种方法来执行我正在寻找的内容(GridCommand.Parse()),但是在控制器中可以使用它,我需要在页面上完成此操作。如果我能找到类似于基于jQuery的框架中提供的MVC扩展的东西,那么这实现起来要容易得多。

提前致谢。

2 个答案:

答案 0 :(得分:3)

在Telerik论坛上询问后,显然在Telerik jQuery框架中没有提供这样做的方法。所以,我继续并实施了一个。

如果有人好奇的话,这是jsfiddle的链接。它只支持过滤字符串和排序字符串,因为我还没有用于解析组字符串。

过滤字符串:

function parseFilterString(filterString) {

        // sample filter: "(Auditor~startswith~'Gabe'~and~Auditor~endswith~'Newell')~and~(Company~contains~'Valve'~and~Company~neq~'EA')";

        // Remove all of the ' characters from the string.
        filterString = filterString.replace(/[']/g, '');

        // Split the string into an array of strings, using the ~ as a delimiter.
        var ss = filterString.split("~"); // ss stands for "split string". I'm clever.

        var F = []; // Used to store all of the parsed filters.
        var fIndex = -1; // Used to track filter index.
        var cIndex = 0; // Used to track filter index within a composite filter object.
        var isComposite = false; // Used to indicate if a composite filter is currently being parsed.

        for (var i = 0; i < ss.length; i++) {
            if (i % 4 == 0) { // Field.
                if (ss[i].indexOf('(') > -1) { // If we're starting a composite object, create a composite object and add it to the parsed filters.
                    F.push({
                        filters: [],
                        logic: ""
                    });
                    fIndex++; // We added an object to the array, so increment the counter.
                    F[fIndex]
                    F[fIndex].filters.push({
                        field: ss[i].replace('(', ''),
                        operator: "",
                        value: ""
                    });
                    cIndex = 0; // We added the first filter to the composite object, so set the counter.
                    isComposite = true;
                }
                else if (isComposite) { // If we're parsing the second filter in a composite filter object, then add the field to the child filter.
                    F[fIndex].filters.push({
                        field: ss[i],
                        operator: "",
                        value: ""
                    });
                    cIndex++; // We added the second filter to the composite object, so increment the counter.
                }
                else { // Add the field as normal.
                    F.push({
                        field: ss[i],
                        operator: "",
                        value: ""
                    });
                    fIndex++; // We added an object to the array, so increment the counter.
                }
            }
            if (i % 4 == 1) { // Operator.
                if (isComposite) {
                    F[fIndex].filters[cIndex].operator = ss[i];
                }
                else {
                    F[fIndex].operator = ss[i];
                }
            }
            if (i % 4 == 2) { // Value.
                if (ss[i].indexOf(')') > -1) {
                    F[fIndex].filters[cIndex].value = ss[i].replace(')', '');
                    isComposite = false;
                }
                else if (isComposite) {
                    F[fIndex].filters[cIndex].value = ss[i];
                }
                else {
                    F[fIndex].value = ss[i];
                }
            }
            if (i % 4 == 3) { // Logic.
                if (isComposite) {
                    F[fIndex].logic = ss[i]; // Add the logic to the composite filter object.
                }
                // If the filter is not composite, the logic will always be "and". So, we just don't do anything if that's the case.
            }
        }

        return {
            filters: F,
            logic: "and"
        };
    };

排序字符串:

function parseSortString(sortString) {
        // sample multi-level sort: "Auditor-asc~Company-desc~Invoice-asc";

        // Split the string into an array of strings, using the ~ as a delimiter.
        var ss = sortString.split("~"); // ss stands for "split string". I'm clever.

        var S = []; // Array containing sort objects.

        for (var i = 0; i < ss.length; i++) {
            var sort = ss[i].split('-'); // Split sort string into field and direction.
            S.push({
                compare: undefined, // This field exists in the sort objects, but is always undefined (as far as I can tell). I added it anyways, to minimize potential future issues.
                dir: sort[1], // Direction.
                field: sort[0] // Field.
            });
        }

        return S;
    };

答案 1 :(得分:0)

var filter =“(审计员以“ Gabe”开始,审计员以“ Newell”结束),并且(公司包含“阀门”和“ neq〜'EA'”);

if (filter == "") {
    return {};
}


if (filter.indexOf("(")  == -1) {
    filter = "(" + filter + ")";
}


var pattern = /(\()([^\(\)]+)(\))/g;
//var pattern = /(.*)/g;
var filterSub = { logic: null, filters: [] };
var filterObject = {};


function parser() {
    var matchParam = filter.match(pattern);
    if (matchParam != null) {

        matchParam.forEach(function (e) {

            var item = e.split('(').join('').split(')').join('');
            var logic = item.indexOf("~or~") > -1 ? "or" : "and";
            var items = item.indexOf("~or~") > -1 ? item.split('~or~') : item.split('~and~');
            filterSub = { logic: null, filters: [] };
            items.forEach(function (c, i) {
                var obj = filterObject[c];
                if (obj == null) {
                    var cArr = c.split("~");
                    obj = {
                        field: cArr[0],
                        operator: cArr[1],
                        value: (cArr[2] || "").split("'").join("")
                    };
                }

                if (items.length == 1) {
                    filterSub = obj;
                } else if (items.length >= 2) {
                    if (filterSub.filters.length == 2) {
                        filterSub = {
                            logic: logic,
                            filters: [obj, filterSub]
                        }
                    } else {
                        filterSub.logic = logic;
                        filterSub.filters.push(obj);
                    }
                } 
            });

            var length = Object.keys(filterObject).length;
            var name = "####" + length;
            filterObject[name] = filterSub;
            filter = filter.replace(e, name);
        });

        if (matchParam.length > 0) {
            parser();
        }
    }
};


parser();

return filterSub;