JqGrid custom formatter with custom parameter

2019-08-05 08:46发布

问题:

I have a question about custom formatters.

What I try to achieve is a currencyFormatter just for the amount with Locale sent by the server, when locale is not define or supported fall back to British English. Something like this:

function currencyFmatter(cellvalue, options, rowdata) {
    return new Intl.NumberFormat([locale, "en-GB"], {minimumFractionDigits: 2, maximumFractionDigits: 2}).format(cellvalue);
}

My problem is how to pass my variable locale to the formatter, I’m pretty sure it has to be a way to do it but right now I don’t see it.

Thanks

回答1:

It's an interesting question! There are many ways to implement your requirements.

1) you can extend your input data returned from the server with additional information which specify the locale of data. For example you can returns "de-DE:10.000,04" instead of "10.000,04" which represent 1000.04 formatted in German locale (where , will be used as the decimal separator and . used as the thousands separator). It allows you to use cellvalue.split(":") to get array ["de-DE", "10.000,04"] with the locale of the number and the number itself

function currencyFmatter(cellvalue, options, rowdata) {
    var data;
    if (typeof cellvalue === "string") {
        data = cellvalue.cellvalue.split(":");
        if (data.length === 2) {
            return new Intl.NumberFormat([data[0], "en-GB"], {
                           minimumFractionDigits: 2,
                           maximumFractionDigits: 2
                       }).format(data[1]);
        }
    }
    return cellvalue;
}

Alternatively you can place the information about locale of the number in separate field (for example numLocale) of the input data and use something like rowdata.numLocale (or rowdata[12] depend on the input format of the JSON data) to access the locale.

2) It could be that all the data returned from the server will be in the same format. In the case it would be not the best way to prepend all numbers with the same prefix "de-DE:". What you can do for example is to extend the data returned from the server with additional field. For example you can use

{
    "total": "12",
    "page": "1",
    "records": "12345",
    "localOfNumbers": "de-DE",
    "rows" : [
        ...
    ]
}

You can access the custom localOfNumbers field inside of beforeProcessing callback. It's very practical callback. It allows you to pre-process the data returned from the server before the data will be processed by jqGrid. I recommend you to read the answer and this one for more code example. What you can do for example is to save localOfNumbers value in some new option of jqGrid (see the answer for more details). Let us you want to have an option gridLocale for the goal. Then you can do something like the following:

beforeProcessing: function (data) {
    if (typeof data.localOfNumbers === "string") {
        $(this).jqGrid("setGridParam", {gridLocale: data.localOfNumbers});
    }
}

To access the new gridLocale option you can use

function currencyFmatter(cellvalue, options, rowdata) {
    var locale = $(this).jqGrid("getGridParam", "gridLocale"); // this.p.gridLocale
}    

3) You can consider to save the information about the locale as column property instead of usage one common gridLocale grid option. To do this you can define the column in colModel like below

{ name: 'col2', width: 200, formatoptions: { colLocale: "en-IN" },
    formatter: function (cellvalue, options, rowdata) {
        // options.colModel.formatoptions.colLocale get you the value
    }

One can set the property of formatoptions.colLocale inside of beforeProcessing too. You can use

{
    "total": "12",
    "page": "1",
    "records": "12345",
    "localOfColumns": {
        "col2": "de-DE",
        "col5": "en-IN"
    },
    "rows" : [
        ...
    ]
}

and

beforeProcessing: function (data) {
    if ($.isPlainObject(data.localOfColumns)) {
        if (typeof data.localOfColumns.col2 === "string") {
            $(this).jqGrid("setColProp", "col2", {
                formatoptions: { colLocale: data.localOfColumns.col2 }
            });
        }
        if (typeof data.localOfColumns.col5 === "string") {
            $(this).jqGrid("setColProp", "col5", {
                formatoptions: { colLocale: data.localOfColumns.col5 }
            });
        }
    }
}

I'm sure that one can suggest even more ways to implement your requirements.