1

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

Pedro Robles
  • 205
  • 5
  • 11

1 Answers1

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.

Community
  • 1
  • 1
Oleg
  • 220,925
  • 34
  • 403
  • 798
  • Hi @Oleg, I'll go with option 2 as all the amounts are formatted with the same locale, although I have to modify many things. I have a page with multiple grids sharing the same locale and passing it as an argument made sense. I thought custom formatters supported optional arguments something like: name:"amount", index:"amount", formatter: currencyFmatter(locale) and then: function currencyFmatter(cellvalue, options, rowdata, locale) { return new Intl.NumberFormat([locale, "en-GB"], {minimumFractionDigits: 2, maximumFractionDigits: 2}).format(cellvalue); } – Pedro Robles Jul 09 '14 at 13:28
  • btw I already knew about German formatting as it's the same as the Spanish one ;-) – Pedro Robles Jul 09 '14 at 13:35
  • @PedroRobles: The value of `formatter` property in `colModel` must be **callback function**. jqGrid calls it. So jqGrid defines which parameters it uses. The syntax `formatter: currencyFmatter(locale)` means that the function `currencyFmatter(locale)` will be executed **once** during creating the grid. the value of `locale` variable should be defined *before* creating the grid. In general `currencyFmatter(locale)` could be closure and returns callback function. Such way could works, but what I wrote in my answer is more simple and should work too. – Oleg Jul 09 '14 at 14:08
  • Yes your answer works fine, I wasn't arguing. Just surprised jqGrid doesn't allow optional parameters for formatters. But definitely setting the locale on beforeProcessing callback saved my day!! Thanks a lot :-) – Pedro Robles Jul 09 '14 at 14:29