indian_currency_input_formatter 1.0.1 copy "indian_currency_input_formatter: ^1.0.1" to clipboard
indian_currency_input_formatter: ^1.0.1 copied to clipboard

A robust TextInputFormatter for Indian currency formatting (lakh/crore grouping), caret-safe and fintech-friendly

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:indian_currency_input_formatter/indian_currency_input_formatter.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Indian Currency Formatter Demo',
      theme: ThemeData(
        useMaterial3: true,
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
      ),
      home: const DemoPage(),
      debugShowCheckedModeBanner: false,
    );
  }
}

class DemoPage extends StatefulWidget {
  const DemoPage({super.key});

  @override
  State<DemoPage> createState() => _DemoPageState();
}

class _DemoPageState extends State<DemoPage> {
  final _formKey = GlobalKey<FormState>();
  final _amountController = TextEditingController();
  final _formattedAmountController = TextEditingController();
  final _customFormatController = TextEditingController();

  num? _parsedValue;
  bool _showIndianFormat = true;

  final _basicFormatter = const IndianCurrencyInputFormatter(showSymbol: true);
  final _customFormatter = IndianCurrencyInputFormatter(
    showSymbol: true,
    symbol: '₹',
    maxDecimals: 3,
    allowNegative: true,
    minValue: -1000000,
    maxValue: 1000000,
  );

  @override
  void dispose() {
    _amountController.dispose();
    _formattedAmountController.dispose();
    _customFormatController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Indian Currency Formatter'),
        actions: [
          IconButton(
            icon:
                Icon(_showIndianFormat ? Icons.language : Icons.currency_rupee),
            onPressed: () {
              setState(() {
                _showIndianFormat = !_showIndianFormat;
              });
            },
            tooltip: _showIndianFormat
                ? 'Switch to International Format'
                : 'Switch to Indian Format',
          ),
        ],
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(24.0),
        child: Form(
          key: _formKey,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              // Basic Usage
              _buildSectionTitle('Basic Usage'),
              TextFormField(
                controller: _amountController,
                keyboardType: TextInputType.numberWithOptions(decimal: true),
                inputFormatters: [_basicFormatter],
                decoration: const InputDecoration(
                  labelText: 'Enter Amount',
                  hintText: '1,23,456.78',
                  border: OutlineInputBorder(),
                  prefixText: '₹ ',
                ),
                onChanged: (value) {
                  setState(() {
                    _parsedValue = parseIndianCurrency(value);
                  });
                },
              ),
              const SizedBox(height: 16),

              // Parsed Value Display
              if (_parsedValue != null) ...[
                Text(
                  'Parsed Value: ${_parsedValue!.toStringAsFixed(2)}',
                  style: Theme.of(context).textTheme.titleMedium,
                ),
                const SizedBox(height: 8),
                Text(
                  'Formatted: ${_formatNumber(_parsedValue ?? 0)}',
                  style: Theme.of(context).textTheme.titleMedium,
                ),
                const Divider(height: 40),
              ],

              // Custom Formatter
              _buildSectionTitle('Custom Formatter'),
              TextFormField(
                controller: _customFormatController,
                keyboardType: TextInputType.numberWithOptions(
                    decimal: true, signed: true),
                inputFormatters: [_customFormatter],
                decoration: const InputDecoration(
                  labelText: 'Amount with Validation (-1,000,000 to 1,000,000)',
                  hintText: '-50,000.50',
                  border: OutlineInputBorder(),
                  prefixText: '₹ ',
                ),
                validator: (value) {
                  if (value == null || value.isEmpty) {
                    return 'Please enter an amount';
                  }
                  final val = parseIndianCurrency(value);
                  if (val < -1000000 || val > 1000000) {
                    return 'Amount must be between -1,000,000 and 1,000,000';
                  }
                  return null;
                },
              ),

              const SizedBox(height: 24),

              // Formatted Display
              _buildSectionTitle('Format Existing Number'),
              TextFormField(
                controller: _formattedAmountController,
                keyboardType: TextInputType.numberWithOptions(decimal: true),
                decoration: const InputDecoration(
                  labelText: 'Enter a number to format',
                  hintText: '1234567.89',
                  border: OutlineInputBorder(),
                ),
              ),
              const SizedBox(height: 16),
              ElevatedButton(
                onPressed: () {
                  final number =
                      double.tryParse(_formattedAmountController.text);
                  if (number != null) {
                    final formatted = _formatNumber(number);
                    ScaffoldMessenger.of(context).showSnackBar(
                      SnackBar(
                        content: Text('Formatted: $formatted'),
                        duration: const Duration(seconds: 2),
                      ),
                    );
                  }
                },
                child: const Text('Format Number'),
              ),

              // Toggle Format
              const SizedBox(height: 24),
              _buildSectionTitle('Toggle Format Style'),
              Text(
                _showIndianFormat
                    ? 'Current Format: Indian (e.g., 12,34,56,789.00)'
                    : 'Current Format: International (e.g., 123,456,789.00)',
                style: Theme.of(context).textTheme.titleMedium,
              ),
              const SizedBox(height: 8),
              TextField(
                keyboardType: TextInputType.numberWithOptions(decimal: true),
                inputFormatters: [
                  IndianCurrencyInputFormatter(
                    showSymbol: true,
                    groupingStyle: _showIndianFormat
                        ? GroupingStyle.indian
                        : GroupingStyle.international,
                  ),
                ],
                decoration: const InputDecoration(
                  labelText: 'Try typing here',
                  border: OutlineInputBorder(),
                ),
              ),
            ],
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton.extended(
        onPressed: () {
          if (_formKey.currentState?.validate() ?? false) {
            ScaffoldMessenger.of(context).showSnackBar(
              const SnackBar(content: Text('Form is valid!')),
            );
          }
        },
        label: const Text('Validate Form'),
        icon: const Icon(Icons.check_circle),
      ),
    );
  }

  Widget _buildSectionTitle(String title) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 16.0),
      child: Text(
        title,
        style: Theme.of(context).textTheme.titleLarge?.copyWith(
              fontWeight: FontWeight.bold,
            ),
      ),
    );
  }

  String _formatNumber(num value) {
    final formatter = IndianCurrencyInputFormatter(
      showSymbol: true,
      symbol: '₹',
      maxDecimals: 2,
    );
    final textEditingValue = formatter.formatEditUpdate(
      TextEditingValue.empty,
      TextEditingValue(text: value.toString()),
    );
    return textEditingValue.text;
  }
}
1
likes
145
points
175
downloads

Publisher

unverified uploader

Weekly Downloads

A robust TextInputFormatter for Indian currency formatting (lakh/crore grouping), caret-safe and fintech-friendly

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on indian_currency_input_formatter

Packages that implement indian_currency_input_formatter