30
Views
5
Comments
Solved
[OutSystems Charts] ODC OutSystemsCharts ColumnChart dynamic number formatting using Locale
OutSystems Charts
Forge asset by OutSystems

To customize the column chart, I use the built in Addons like Y Axis and ChartSeriesStyling. But in order to add more specific styling I have a JS node in the Initialized event of the chart that sets the HighChart options. Doing this, I have been able to change the decimalPoint and thousandsSep. But I actually want the chart to be dynamic based on the user's locale, by using navigator.language or something similar. However, setting the locale does not change the appearance of the number formatting, even though it does work when testing in JSfiddle.

This is the code in the JS node, everything else works apart from the locale.

const options = {    lang: {        // decimalPoint: '.',        // thousandsSep: ',',        locale: 'nl-NL'        // locale: navigator.language,        }}const chartConfig = {      chart: {        width: 90,        margin: 0,        marginBottom: 30,        marginTop: 0,    },    xAxis: {        lineWidth: 0,        rotation: 0,        labels: {            enabled: false,            useHTML: true,            rotation: 0,            distance: 4,            style: {                whiteSpace: 'pre-wrap',                fontSize: '12px',                fontFamily: 'rubik',                textAlign: 'center',                color: 'black'            },        },    },    tooltip: {        enabled: false    },    plotOptions: {        column: {            pointWidth: 42,            borderRadius: {                radius: 4,                where: 'all',            },            borderWidth: 0,            cursor: 'auto',            dataLabels: {                style: {                    fontWeight: 400,                    fontFamily: 'rubik',                    fontSize: 12,                }            }        }    },};Highcharts.setOptions(options);OutSystems.ChartAPI.Chart.SetProviderConfigs($parameters.ChartWidgetId, JSON.stringify(chartConfig));


P.S. I've added this JS code in a txt file because I can't format it in the rich text editor for some reason

JS_SetHighChartsConfig.txt
2020-03-27 18-58-43
Fred Derks
Solution

The workaround I have now implemented consists of ignoring the lang.locale option and instead retrieving the decimal and thousands separator based on the user locale as demonstrated here:

https://stackoverflow.com/questions/33159354/how-do-i-find-the-decimal-separator-for-current-locale-in-javascript

I encapsulated that function in a client action and I am then using those outputs as the lang.decimalPoint and lang.thousandsSep options. 

2020-07-21 19-28-50
Rajat Agrawal
Champion

Hi @Fred Derks 

Please try below JS code 

const userLocale = navigator.language || 'en-US'; 

const options = {

    lang: {

        locale: userLocale, // Use the dynamically detected user language

        decimalPoint: userLocale === 'nl-NL' ? ',' : '.', 

        thousandsSep: userLocale === 'nl-NL' ? '.' : ',', 

    }

};

const chartConfig = {

    chart: {

        width: 90,

        margin: 0,

        marginBottom: 30,

        marginTop: 0,

    },

    xAxis: {

        lineWidth: 0,

        rotation: 0,

        labels: {

            enabled: false,

            useHTML: true,

            rotation: 0,

            distance: 4,

            style: {

                whiteSpace: 'pre-wrap',

                fontSize: '12px',

                fontFamily: 'rubik',

                textAlign: 'center',

                color: 'black',

            },

        },

    },

    tooltip: {

        enabled: false,

    },

    plotOptions: {

        column: {

            pointWidth: 42,

            borderRadius: { radius: 4, where: 'all' },

            borderWidth: 0,

            cursor: 'auto',

            dataLabels: {

                style: {

                    fontWeight: 400,

                    fontFamily: 'rubik',

                    fontSize: 12,

                },

            },

        },

    },

};

Highcharts.setOptions(options);

OutSystems.ChartAPI.Chart.SetProviderConfigs($parameters.ChartWidgetId, JSON.stringify(chartConfig));

Regards ,

Rajat

2020-03-27 18-58-43
Fred Derks

Thanks, Rajat,

I was also considering some sort of work-around like this, and although it works, the problem is that there are probably many more locales than just 'nl' that use '.' as thousands separator. I want to adhere to the users actual locale as much as possible. Just like we can in other parts of our app. (There are countries that use a space as thousands separator too, for example.) I know that the lang: locale option can be used for this but it just doesn't seem to be working. Perhaps the option is already being used under the hood and can't be overwritten?

2020-07-21 19-28-50
Rajat Agrawal
Champion

Please try below one


const userLocale = navigator.language || 'en-US'; 

const numberFormatter = new Intl.NumberFormat(userLocale);

const parts = numberFormatter.formatToParts(2457.17);

const decimalPoint = parts.find(part => part.type === 'decimal')?.value || '.';

const thousandsSep = parts.find(part => part.type === 'group')?.value || ','; 

const options = {

    lang: {

        locale: userLocale, 

        decimalPoint: decimalPoint, 

        thousandsSep: thousandsSep, 

    }

};

const chartConfig = {

    chart: {

        width: 90,

        margin: 0,

        marginBottom: 30,

        marginTop: 0,

    },

    xAxis: {

        lineWidth: 0,

        rotation: 0,

        labels: {

            enabled: false,

            useHTML: true,

            rotation: 0,

            distance: 4,

            style: {

                whiteSpace: 'pre-wrap',

                fontSize: '12px',

                fontFamily: 'rubik',

                textAlign: 'center',

                color: 'black',

            },

        },

    },

    tooltip: {

        enabled: false,

    },

    plotOptions: {

        column: {

            pointWidth: 42,

            borderRadius: { radius: 4, where: 'all' },

            borderWidth: 0,

            cursor: 'auto',

            dataLabels: {

                style: {

                    fontWeight: 400,

                    fontFamily: 'rubik',

                    fontSize: 12,

                },

            },

        },

    },

};

Highcharts.setOptions(options);

OutSystems.ChartAPI.Chart.SetProviderConfigs($parameters.ChartWidgetId, JSON.stringify(chartConfig));


2020-03-27 18-58-43
Fred Derks

Yes, that's basically what I did in the comment I posted below. 

Thanks for the help

2020-03-27 18-58-43
Fred Derks
Solution

The workaround I have now implemented consists of ignoring the lang.locale option and instead retrieving the decimal and thousands separator based on the user locale as demonstrated here:

https://stackoverflow.com/questions/33159354/how-do-i-find-the-decimal-separator-for-current-locale-in-javascript

I encapsulated that function in a client action and I am then using those outputs as the lang.decimalPoint and lang.thousandsSep options. 

Community GuidelinesBe kind and respectful, give credit to the original source of content, and search for duplicates before posting.