Locale 'PT' don't work

I have this snnipet that aquire here in the forum, but dont function to numeric text box.
I need help, pls

import React, {useEffect, useState} from 'react';
import {Statement} from "../../interfaces/Statement.ts";
import {useCategories} from '../../hooks/useCategories';
import './StatementForm.css';
import ReactDOM from "react-dom";
import {NumericTextBoxComponent} from "@syncfusion/ej2-react-inputs";
import {localizeSyncfusion} from "../../syncfusionLocalizationManager.ts";
import {Language} from "../../language.ts";
import {loadCldr, setCulture, setCurrencyCode} from '@syncfusion/ej2-base';
import * as numberingSystems from 'cldr-data/supplemental/numberingSystems.json';
import * as gregorian from 'cldr-data/main/pt/ca-gregorian.json';
import * as numbers from 'cldr-data/main/pt/numbers.json';
import * as currencies from 'cldr-data/main/pt/currencies.json';
import * as currencyData from 'cldr-data/supplemental/currencyData.json';
import * as timeZoneNames from 'cldr-data/main/pt/timeZoneNames.json';

interface StatementFormProps {
initialData?: Statement;
onSubmit: (statement: Statement) => void;
onCancel: () => void;
}


loadCldr(numberingSystems, gregorian, numbers, timeZoneNames, currencies, currencyData );
setCulture('pt');
setCurrencyCode('BRL');
export const StatementForm: React.FC<StatementFormProps> = ({
initialData,
onSubmit,
onCancel
}) => {

localizeSyncfusion(Language.Portuguese);
const {categories} = useCategories();
// Referência para o portal
const modalRoot = document.getElementById('modal-root') || document.body;

const [formData, setFormData] = useState<Statement>({
descricao: '',
valor: 0,
tipo: 'DESPESA',
dataVencimento: new Date().toISOString().split('T')[0],
status: 'PENDENTE',
anoCompetencia: new Date().getFullYear(),
mesCompetencia: new Date().getMonth() + 1,
categoriaId: undefined,
observacao: ''
});

useEffect(() => {
if (initialData) {
// Formatar datas para o formato esperado pelos inputs
const formattedData = {
...initialData,
dataVencimento: initialData.dataVencimento ?
(typeof initialData.dataVencimento === 'string' ?
initialData.dataVencimento.split('T')[0] :
initialData.dataVencimento.toISOString().split('T')[0]) :
new Date().toISOString().split('T')[0],
dataPagamento: initialData.dataPagamento ?
(typeof initialData.dataPagamento === 'string' ?
initialData.dataPagamento.split('T')[0] :
initialData.dataPagamento.toISOString().split('T')[0]) :
undefined
};
setFormData(formattedData);
}
}, [initialData]);

const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) => {
const {name, value, type} = e.target;
let processedValue: string | number = value;

// Processar tipos especiais
if (type === 'number') {
processedValue = parseFloat(value);
}

setFormData(prev => ({
...prev,
[name]: processedValue
}));
};
const handleNumericChange = (args: any) => {
setFormData(prev => ({
...prev,
valor: args.value
}));
};
const handleSelectChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
const {name, value} = e.target;

if (name === 'categoriaId') {
const selectedCategory = categories.find(cat => cat.id.toString() === value);

setFormData(prev => ({
...prev,
categoriaId: parseInt(value),
categoriaNome: selectedCategory?.nome || ''
}));
} else {
setFormData(prev => ({
...prev,
[name]: value
}));
}
};

const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
onSubmit(formData);
};

// Filtrar categorias pelo tipo da transação
const filteredCategories = categories?.filter(cat =>
cat.tipo === formData.tipo && cat.ativo
) || [];

return ReactDOM.createPortal(
<div className="form-dialog-overlay">
<div className="form-dialog-content">
<div className="form-dialog-header">
<h2>{initialData ? 'Editar Transação' : 'Nova Transação'}</h2>
<button className="close-btn" onClick={onCancel}>×</button>
</div>

<form onSubmit={handleSubmit} className="statement-form">
<div className="form-row">
<div className="form-group">
<label htmlFor="tipo">Tipo</label>
<select
id="tipo"
name="tipo"
value={formData.tipo}
onChange={handleSelectChange}
required
>
<option value="RECEITA">Receita</option>
<option value="DESPESA">Despesa</option>
</select>
</div>

<div className="form-group">
<label htmlFor="categoriaId">Categoria</label>
<select
id="categoriaId"
name="categoriaId"
value={formData.categoriaId}
onChange={handleSelectChange}
required
>
<option value="">Selecione uma categoria</option>
{filteredCategories.map(category => (
<option key={category.id} value={category.id}>
{category.nome}
</option>
))}
</select>
</div>
</div>

<div className="form-group">
<label htmlFor="descricao">Descrição</label>
<input
id="descricao"
name="descricao"
type="text"
value={formData.descricao || ''}
onChange={handleChange}
required
maxLength={100}
/>
</div>

<div className="form-row">

<div className="form-group">
<label htmlFor="valor">Valor</label>
<NumericTextBoxComponent
cssClass="custom-numeric-input"
min={0}
step={0.01}
value={formData.valor}
locale='pt'
// currency={'BRL'}
format={'C2'}
decimals={2}
change={handleNumericChange}
/>
</div>
.

<div className="form-group">
<label htmlFor="status">Status</label>
<select
id="status"
name="status"
value={formData.status}
onChange={handleSelectChange}
required
>
<option value="PENDENTE">Pendente</option>
<option value="PAGO">Pago</option>
<option value="CANCELADO">Cancelado</option>
</select>
</div>
</div>

<div className="form-row">
<div className="form-group">
<label htmlFor="dataVencimento">Data de Vencimento</label>
<input
id="dataVencimento"
name="dataVencimento"
type="date"
value={formData.dataVencimento || ''}
onChange={handleChange}
required
/>
</div>

<div className="form-group">
<label htmlFor="dataPagamento">Data de Pagamento</label>
<input
id="dataPagamento"
name="dataPagamento"
type="date"
value={formData.dataPagamento || ''}
onChange={handleChange}
disabled={formData.status !== 'PAGO'}
/>
<small>Disponível apenas para status "Pago"</small>
</div>
</div>

<div className="form-row">
<div className="form-group">
<label htmlFor="anoCompetencia">Ano de Competência</label>
<input
id="anoCompetencia"
name="anoCompetencia"
type="number"
min="2020"
max="2050"
value={formData.anoCompetencia || new Date().getFullYear()}
onChange={handleChange}
required
/>
</div>

<div className="form-group">
<label htmlFor="mesCompetencia">Mês de Competência</label>
<input
id="mesCompetencia"
name="mesCompetencia"
type="number"
min="1"
max="12"
value={formData.mesCompetencia || (new Date().getMonth() + 1)}
onChange={handleChange}
required
/>
</div>
</div>

<div className="form-group">
<label htmlFor="observacao">Observação</label>
<textarea
id="observacao"
name="observacao"
value={formData.observacao || ''}
onChange={handleChange}
rows={3}
/>
</div>

<div className="form-actions">
<button type="button" className="btn-cancel" onClick={onCancel}>
Cancelar
</button>
<button type="submit" className="btn-submit">
{initialData ? 'Atualizar' : 'Salvar'}
</button>
</div>
</form>
</div>
</div>,
modalRoot
);
}

3 Replies

PK Priyanka Karthikeyan Syncfusion Team April 7, 2025 02:42 PM UTC

Hi Jorge Nascimento,


 

Thank you for reaching out to us. 

 

To properly load the "pt" culture in the React NumericTextBox component, we have created a sample based on your requirements. Please find the code snippet and attached sample for your reference.

App.js

 

import { NumericTextBoxComponent } from '@syncfusion/ej2-react-inputs';

import React, { useState } from 'react';

import {

  L10n,

  loadCldr,

  setCulture

} from "@syncfusion/ej2-base";

import './App.css';

 

loadCldr(  // loding cldr-data

  require('cldr-data/supplemental/numberingSystems.json'),

  require('cldr-data/main/pt/ca-gregorian.json'),

  require('cldr-data/main/pt/numbers.json'),

  require('cldr-data/main/pt/currencies.json'),

  require('cldr-data/main/pt/timeZoneNames.json'));

 

 L10n.load({

   'pt': {

        'numerictextbox': {

          placeholder: 'Enter value'

        }

      }

 });

function App() {

    return (<div style={{marginTop: '100px'}}>

      <NumericTextBoxComponent

          locale="pt"

        />

      </div>);

}

 

export default App;

 

 

 

 

Regards,

Priyanka K



Attachment: reactculture_d9c19d7d.zip


JN Jorge Nascimento April 7, 2025 11:14 PM UTC

Priyanka K


I was trying your snippet and it was ok, but when I move the code to my project it doesn't work.

I'm using TS with vite.

Is there a possibility to do global configuration for the project all in one place?



PK Priyanka Karthikeyan Syncfusion Team April 21, 2025 02:29 PM UTC

Hi Jorge Nascimento,


We apologies for the delay.

 

We have created a sample demonstrating the use of the NumericTextBox component with localization in a React Vite + TypeScript setup. Please find the code snippet and sample attached below for your reference:

 

 

import { NumericTextBoxComponent } from '@syncfusion/ej2-react-inputs';

 

import { L10n, loadCldr } from '@syncfusion/ej2-base';

import './App.css';

 

 

import * as currencies from 'cldr-data/main/pt/currencies.json';

   import * as numbers from 'cldr-data/main/pt/numbers.json';

   import * as gregorian from 'cldr-data/main/pt/ca-gregorian.json';

   import * as currencyData from 'cldr-data/supplemental/currencyData.json';

   import * as numberingSystems from 'cldr-data/supplemental/numberingSystems.json';

 

   loadCldr(numberingSystems, currencies, numbers, currencyData, gregorian);

 

L10n.load({

  pt: {

    numerictextbox: {

      placeholder: 'Enter value',

    },

  },

});

function App() {

  return (

    <div style={{ marginTop: '100px' }}>

      <NumericTextBoxComponent locale="pt" />

    </div>

  );

}

 

export default App;

 

 

Regards,

Priyanka K


Attachment: React_vite_5436e82c.zip

Loader.
Up arrow icon