简体   繁体   中英

Handsontable - I found a bug when copying/pasting a german numeric value

I want to use the Javascript grid framework Handsontable for my next project, but I found a small bug, which is a blocking point for using this lib. :-(

I have to show a table with german prices, eg "18,50 €". The german language has a , (comma) as decimal point. By default handsontable has only the language "en" for the embedded "numeral.js" helper library. So added the german (de) language definition for numeral.js. The cell format is defined as "0.00 $" and it will show correctly as "18,50 €" in the grid.

But when I select a cell with eg "1,50 €" (single click on the cell), then press "Ctrl+C" and paste it again with Ctrl+V into another cell. The new cell has the wrong value "15,00 €", because the copied value in the clipboard is "1.5" which then will be pasted as "15".

HTML:

<div id="exampleGrid"></div>

Javascript:

(function () {
    var language = {
        delimiters: {
            thousands: '.',
            decimal: ','
        },
        abbreviations: {
            thousand: 'k',
            million: 'm',
            billion: 'b',
            trillion: 't'
        },
        ordinal: function (number) {
            return '.';
        },
        currency: {
            symbol: '€'
        }
    };
    if (typeof window !== 'undefined' && this.numeral && this.numeral.language)  {
        this.numeral.language('de', language);
    }
}());

$("#exampleGrid").handsontable({
    data: [ [1.5], [] ],
    rowHeaders: true,
    colHeaders: true,
    columns: [
        { type: 'numeric', format: '0.00 $', language: 'de'}
    ]
});

I have created a jsfiddle for demonstrating the problem: http://jsfiddle.net/hU6Kz/4873/

I work with version 0.23.0. I tried a lot to workaround this bug (hooks, custom validators, ...) but nothing helps, because I didn't get the original value "1.5" inside the event callbacks. I only get the wrong value "15". You can see this, when using "beforeChange" hook as additional option in the handsontable constructor:

beforeChange: function (changes, source) {
        for (var i = changes.length - 1; i >= 0; i--) {
            console.log('Changes: source:' + source + ' row:' + changes[i][0] + ' col:' + changes[i][1] + ' old:' + changes[i][2] + ' new:' + changes[i][3]);
        }
    }

When I do the copy and paste of "1,50 €" then the console shows:

Changes: source:paste row:1 col:0 old:null new:15

My idea was to recognize the 1.50 and change it to 1,50 before handsontable updates the cell, but the new value is already "15", so no chance to see the original copied value. :-(

Perhaps someone of you has an idea.

Thanks in advance.

Update:

In the source code I found the function 'validateChanges' which does the following:

if (numeral.validate(changes[i][3])) {
    changes[i][3] = numeral().unformat(changes[i][3]);
}

When the current numeral language is 'de' and call this, the result ist "15". So here is the problem, but how to solve it?

numeral().unformat('1.5 €')

And now I understand, why I didn't get the original copied value when the hook "beforeChange" is called. Because this 'validateChanges' is called before the hook is triggered.

And now?

Replace on line 24646:

if (languages[currentLanguage].delimiters.decimal !== '.') {
  string = string.replace(/\./g, '').replace(languages[currentLanguage].delimiters.decimal, '.');
}

With this:

if (languages[currentLanguage].delimiters.decimal !== '.') {
  string = string.replace(languages[currentLanguage].delimiters.decimal, '.');
}

The first string replace removes the decimal point from the raw data.

Note: I'm not that familiar with this js library, this could lead to unintended consequences. Discuss the problem with the project maintainers on their github page.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM