4

I am using the Table Component of Ant Design v2.x and I cannot upgrade. I would like to change the formatting of numbers in row-edit mode, since currently it is inconsistent: In Display mode I have German formatting (as desired), but once I click edit, numbers are formatted with American decimal separators:

Screenshot of the issue

I understand that the table-component encapsulates an Input-Number component which has the parameter decimalSeparator which I have to adjust. It is not at all obvious to me how I can pass-through that parameter from my parent (table) component column property to the underlying input-number component.

As minimal code base to demonstrate that, let us consider the Typescript example code from https://ant.design/components/table/#components-table-demo-edit-row and focus on the column age. Assume that it is not an age, but rather a Value (e.g. of a trade). The (correct) formatting in the 2nd row of my screenshot I obtain with a render-function like this:

x.toLocaleString("de-DE", { style: 'currency', currency: ccy, currencyDisplay: "code", maximumFractionDigits: 2 });

where x is the value to be formatted and ccy is the currency-string to be displayed, in the screenshot it was just empty.

What I am able to do is to specify whether a column is a number, a string, or something else. In the example source code, the corresponding part is:

interface Item {
  key: string;
  name: string;
  age: number;
  address: string;
}

Looking forward to your help!

B--rian
  • 5,578
  • 10
  • 38
  • 89
  • The example https://codesandbox.io/s/i1bk4?file=/index.js: suggests that in the `form` of the table we could adjust the formatting. It looks like in the linked example, an `EditableCell` is constructed, which is handed over to the table which in turn uses that as editor. I am just not quite sure how to adjust my existing, inherited code to that. Inherited is meant quite literally here, but that's a different issue: https://stackoverflow.com/questions/58285455/ – B--rian May 12 '20 at 09:28
  • 1
    I can help to adjust your code if you provide a minimal working example. – oozywaters May 12 '20 at 09:46

3 Answers3

3

InputNumber has formatter and parser props that you can use to format currency values.

Another easier option, that I would recommend, is to use input mask. Here is an example involving react-number-format:

import React, { useState } from "react";
import ReactDOM from "react-dom";
import NumberFormat from "react-number-format";
import { Table, Input, Form } from "antd";

const EditableCell = ({
  editing,
  dataIndex,
  title,
  inputType,
  record,
  index,
  children,
  ...restProps
}) => {
  const inputNode =
    inputType === "number" ? (
      <NumberFormat
        customInput={Input}
        thousandSeparator="."
        decimalSeparator=","
        decimalScale={2}
      />
    ) : (
      <Input />
    );
  return (
    <td {...restProps}>
      {editing ? (
        <Form.Item
          name={dataIndex}
          style={{
            margin: 0
          }}
          rules={[
            {
              required: true,
              message: `Please Input ${title}!`
            }
          ]}
        >
          {inputNode}
        </Form.Item>
      ) : (
        children
      )}
    </td>
  );
};

Also, you can check out a live example over here.

oozywaters
  • 1,171
  • 1
  • 8
  • 17
  • Thanks for your suggestion, may you explain a bit what an input-mask is and what the idea behind your suggestion is? My issue is that I am not so fluent with reatjs-specific terms - sorry for that, it is just not my native language :-) – B--rian May 12 '20 at 08:46
  • 1
    Input mask is not a react specific term. You can refer to this article https://en.wikipedia.org/wiki/Input_mask for more information. There are several implementations of input mask for reactjs, such as react-input-mask, react-text-mask and react-number-format, mentioned in the answer. The idea behind my suggestion is to avoid implementing complex `formatter` and `parser` functions by yourself and take advantage of ready solutions in spite of causing an extra dependency. – oozywaters May 12 '20 at 09:19
1

By trial and error, I finally understood how the formatter and parser of the InputNumber component works, there was close to no documentation at https://2x.ant.design/components/table/

I ended up doing the following, which is not exactly pretty, but works:

<InputNumber
  defaultValue={this.props.value !== null ? parseFloat(this.props.value) : null}
  // This is what 2x.antd.design suggests to do it:
  // formatter={value => ` ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
  // parser={value => value.replace(/\$\s?|(,*)/g, "")}

  // This my solution for German numbers
  formatter={value => ` ${value}`.replace(/\./,',').replace(/\B(?=(\d{3})+(?!\d))/g, '.')}
  parser={x => parseFloat(`${x}`.replace(/,/, '#').replace(/\./g, '').replace(/#/,'.')) }  

  onChange={this.handleChange}
/>

The idea of the formatter is to first replace the decimal separator . with ,. The replace(/\B(?=(\d{3})+(?!\d))/g, ',') is to find globally all 3-digit groups \d{3}, and replace any kind of thousand-separator with ., the \B(?=(\d{3})+(?!\d)) finds all but the last ,.

Before writing things back into the state variable this.props.value, we have to undo that replacement, so we first replace the comma as decimal separator with some placeholder #, then delete all . in the string, and finally make revert the placeholder to the . as decimal separator which can be understood by parseFloat.

B--rian
  • 5,578
  • 10
  • 38
  • 89
  • @oozywaters I figured it out myself, but it was indeed not straight-forward. Are my explanations making sense? – B--rian May 29 '20 at 14:34
-1

Please use

const formatValue = value => value.toLocaleString("en-IN");

You can get the desired format from fromate LocaleString.

ar-SA Arabic (Saudi Arabia)
bn-BD Bangla (Bangladesh)
bn-IN Bangla (India)
cs-CZ Czech (Czech Republic)
da-DK Danish (Denmark)
de-AT Austrian German
de-CH "Swiss" German
de-DE Standard German (as spoken in Germany)
el-GR Modern Greek
en-AU Australian English
en-CA Canadian English
en-GB British English
en-IE Irish English
en-IN Indian English
en-NZ New Zealand English
en-US US English
en-ZA English (South Africa)
es-AR Argentine Spanish
es-CL Chilean Spanish
es-CO Colombian Spanish
es-ES Castilian Spanish (as spoken in Central-Northern Spain)
es-MX Mexican Spanish
es-US American Spanish
fi-FI Finnish (Finland)
fr-BE Belgian French
fr-CA Canadian French
fr-CH "Swiss" French
fr-FR Standard French (especially in France)
he-IL Hebrew (Israel)
hi-IN Hindi (India)
hu-HU Hungarian (Hungary)
id-ID Indonesian (Indonesia)
it-CH "Swiss" Italian
it-IT Standard Italian (as spoken in Italy)
ja-JP Japanese (Japan)
ko-KR Korean (Republic of Korea)
nl-BE Belgian Dutch
nl-NL Standard Dutch (as spoken in The Netherlands)
no-NO Norwegian (Norway)
pl-PL Polish (Poland)
pt-BR Brazilian Portuguese
pt-PT European Portuguese (as written and spoken in Portugal)
ro-RO Romanian (Romania)
ru-RU Russian (Russian Federation)
sk-SK Slovak (Slovakia)
sv-SE Swedish (Sweden)
ta-IN Indian Tamil
ta-LK Sri Lankan Tamil
th-TH Thai (Thailand)
tr-TR Turkish (Turkey)
zh-CN Mainland China, simplified characters
zh-HK Hong Kong, traditional characters
zh-TW Taiwan, traditional characters
Abhishek Gurjar
  • 7,426
  • 10
  • 37
  • 45