3

I'm using loadonce to get all data up front and then doing sorting and filtering locally.

One of my column values is an array of objects. In the colModel option I use a formatter function that looks like this:

function my_formatter(cellValue) 
{ 
    return $.map(cellValue, function(element) {return element.human_readable_name;}).join(', '); 
}

I also use a custom sorting function that simply returns the length of the array.

The problem I have is that the toolbar filtering and multi-field dialog filtering aren't working. They seem to be searching on [objects].toString() rather than the formatted value. So I get hits when I search for "[object Object]", but not when I search for the actual values.

Is there a way to get the local filtering to use the formatted value?

Edit based on Oleg's response:

I adapted Oleg's code to add per-column filter formatting. It seems to work well. I removed the _toStr replacement because it didn't seem necessary -- I think it's used to modify the search term (which makes sense in Oleg's accent-stripping case, but not in mine).

// Causes local filtering to use custom formatters for specific columns.
// formatters is a dictionary of the form:
// { "column_name_1_needing_formatting": "column1FormattingFunctionName",
//   "column_name_2_needing_formatting": "column2FormattingFunctionName" }
// Note that subsequent calls will *replace* all formatters set by previous calls.
function setFilterFormatters(formatters)
{
    function columnUsesCustomFormatter(column_name)
    {
        for (var col in formatters)
        {
            if (col == column_name)
            return true;
        }
        return false;
    }

    var accessor_regex = /jQuery\.jgrid\.getAccessor\(this\,'(.+)'\)/;

    var oldFrom = $.jgrid.from;
    $.jgrid.from = function(source, initialQuery) {
        var result = oldFrom(source, initialQuery);
        result._getStr = function(s) {
            var column_formatter = 'String';

            var column_match = s.match(accessor_regex, '$1');
            if (column_match && columnUsesCustomFormatter(column_match[1]))
            {
                column_formatter = formatters[column_match[1]];
            }

            var phrase=[];
            if(this._trim) {
                phrase.push("jQuery.trim(");
            }
            phrase.push(column_formatter+"("+s+")");
            if(this._trim) {
                phrase.push(")");
            }
            if(!this._usecase) {
                phrase.push(".toLowerCase()");
            }
            return phrase.join("");
        }

        return result;
    }; 
}

And it gets called like this:

setFilterFormatters({'column_with_array_of_objects':'my_formatter'});

Testing suggests that this works for 'contains', 'does not contain', 'equals', 'does not equal' (and probably 'begins with' and the other simple string comparisons -- but I'm not using them).

Thanks, Oleg.

adam-p
  • 660
  • 6
  • 16

1 Answers1

2

In my old answer in the trirand forum I described how to implement custom local filtering and sorting. The demo shows accent free searching and sorting. If you use the same technique you can overwrite some jqGrid functions used for searching (_toStr and _getStr for example) and implement it so that in case of arrays you will use your own it's implementation.

To make my answer more Google friendly I include small code fragment

function myAccentRemovement(s) {
    // the s parameter is always string
    s = s.replace(/[àáâãäå]/gi,'a');
    s = s.replace(/[èéêë]/gi,'e');
    s = s.replace(/[ìíîï]/gi,'i');
    s = s.replace(/[òóôõöø]/gi,'o');
    s = s.replace(/[ùúûü]/gi,'u');
    s = s.replace(/[ýÿ]/gi,'y');
    s = s.replace(/æ/gi,'ae');
    s = s.replace(/œ/gi,'oe');
    s = s.replace(/ç/gi,'c');
    s = s.replace(/š/gi,'s');
    s = s.replace(/ñ/gi,'n');
    s = s.replace(/ž/gi,'z');
    return s;
}
//...
var oldFrom = $.jgrid.from;
$.jgrid.from = function(source,initalQuery){
    var result = oldFrom(source,initalQuery);
    var old_toStr = result._toStr;
    result._toStr=function(s) {
        return myAccentRemovement(old_toStr(s));
    };
    result._getStr=function(s) {
        var phrase=[];
        if(this._trim){
            phrase.push("jQuery.trim(");
        }
        phrase.push("myAccentRemovement(String("+s+"))");
        if(this._trim){
            phrase.push(")");
        }
        if(!this._usecase){
            phrase.push(".toLowerCase()");
        }
        return phrase.join("");
    }
    return result;
}

It will be solve the problem. I can't gives you more exact suggestions because you posted no information about the exact structure of data which you use.

Oleg
  • 220,925
  • 34
  • 403
  • 798
  • Thanks, Oleg. Your code doesn't quite work for me because it doesn't allow me to format values differently for different columns. Replacing _getStr() replaces it for *all* column filtering, not just the one that needs formatting. If all of my column used the same formatting, I could replace your "myAccentRemovement(String" with "my_formatter". – adam-p Apr 28 '11 at 20:13
  • @adampx: It's difficult to help you because you don't post the code which you use. For example [this.equals](https://github.com/tonytomov/jqGrid/blob/v4.0.0/js/grid.base.js#L498) and all other methods have the column name as the first parameter. The function `_getStr` (which I overwride in my demo) will be called inside of the `this.equals` or `this.contains`. The function `_getStr` will be called with the column name. So one do can implement all what you need, but you should make more changes in my demo. – Oleg Apr 28 '11 at 20:36