flutter_multi_table 0.0.3 copy "flutter_multi_table: ^0.0.3" to clipboard
flutter_multi_table: ^0.0.3 copied to clipboard

A Flutter packages for creating dynamic, multi-column tables with features like dropdowns, validation, and read-only cells. Ideal for interactive table inputs.

flutter_multi_table #

pub package likes popularity pub points GitHub stars GitHub forks

A Flutter packages for creating dynamic, multi-column tables with features like dropdowns, validation, and read-only cells. Ideal for interactive table inputs.

💰 You can help me by Donating #

BuyMeACoffee

Demo #

Input Data Mode Potrait Get Data Mode Potrait
input-data-table result-data-table
Input Data Mode Landscape Get Data Mode Landscape
input-data-table result-data-table

Features #

  • ✨ Fully customizable table layout and styling
  • 📝 Support for both text input and dropdown cells
  • 🔒 Configurable read-only cells
  • ✅ Built-in validation support
  • 📱 Responsive design for both portrait and landscape orientations
  • 🎨 Customizable styling for headers, cells, and error messages
  • 🔄 Real-time data updates with onChange callbacks
  • 💾 Easy data management with dedicated controller

Supported platforms #

  • Flutter Android
  • Flutter iOS
  • Flutter web
  • Flutter desktop
  • Flutter macOS
  • Flutter Linux

Installation #

  1. Add flutter_multi_table.dart: <latest-version> to your pubspec.yaml dependencies. And import it: Get the latest version in the 'Installing' tab on pub.dev
dependencies:
  flutter_multi_table: <latest-version>
flutter pub add flutter_multi_table
  1. Run pub get.
flutter pub get
  1. Import package.
import 'package:flutter_multi_table/flutter_multi_table.dart';

Basic Usage #

// 1. Define your headers
List headers = [
  'No',
  'Name',
  'Age',
  'City',
  'Status',
];

// 2. Create initial data
List<Map> initialData = [
  {
    'No': '1',
    'Name': 'John',
    'Age': '',
    'City': 'New York',
    'Status': 'Active',
  },
  {
    'No': '2',
    'Name': 'Alice',
    'Age': '',
    'City': 'London',
    'Status': 'Inactive',
  },
];

// 3. Initialize controller
FlutterMultiTableController controller = FlutterMultiTableController(
  initialData: initialData,
  headers: headers,
);

// 4. Configure table
FlutterMultiTableConfig config = FlutterMultiTableConfig(
  headers: headers,
  hint: '....',
);

// 5. Use the widget
FlutterMultiTable(
  controller: controller,
  config: config,
)

Advanced Configuration #

Table Configuration #

FlutterMultiTableConfig config = FlutterMultiTableConfig(
  headers: headers,
  hint: '....',

  // Define which cells are read-only
  isReadOnly: (row, column) {
    if (column == 0 || column == 1 || column == 3 || column == 4) {
      return true;
    }
    return false;
  },

  // Configure dropdown cells
  isDropdown: (row, column) {
    if (column == 2 && (row != 1 && row != 13)) {
      return true;
    }
    return false;
  },
  dropdownOptions: ['Jakarta', 'New York', 'London', 'Tokyo', 'Paris'],

  // Handle value changes
  onChanged: (row, column, value) {
    print('Cell ($row, $column) changed to: $value');
  },

  // Validation
  validator: (row, column, value) {
    if (column == 2 && value.isEmpty) {
      return 'Data wajib diisi';
    }
    return null;
  },

  // Dropdown validation
  dropdownValidator: (row, column, value) {
    if (column == 2 && (value == null || value.isEmpty)) {
      return 'Data wajib diisi';
    }
    return null;
  },

  // Styling
  headerTextStyle: TextStyle(
    fontSize: 10,
    color: Colors.white,
    fontWeight: FontWeight.w700,
  ),
  errorTextStyle: TextStyle(fontSize: 8, color: Colors.red),
  cellTextStyle: TextStyle(
    fontSize: 6,
    fontWeight: FontWeight.w600,
  ),
  cellWidth: MediaQuery.of(context).size.width * 0.182,
  cellHeight: MediaQuery.of(context).size.height * 0.04,
  hintTextStyle: TextStyle(
    fontSize: 8,
    fontWeight: FontWeight.w400,
  ),
);

FlutterMultiTableController #

Main controller class for managing table data and state:

Constructor

FlutterMultiTableController({
  required List<Map> initialData,
  required List headers,
})

Methods

  • updateCell(int row, int column, String value): Updates specific cell value
  • getCellValue(int row, int column): Gets value from specific cell
  • setDropdownError(int row, int column, String? error): Sets dropdown error message
  • getDropdownError(int row, int column): Gets dropdown error message
  • dispose(): Cleans up resources

FlutterMultiTableConfig #

Configuration class for customizing table appearance and behavior:

FlutterMultiTableConfig({
  required List headers,
  String hint = "",
  bool Function(int row, int column)? isReadOnly,
  bool Function(int row, int column)? isDropdown,
  List? dropdownOptions,
  void Function(int row, int column, String value)? onChanged,
  String? Function(int row, int column, String value)? validator,
  String? Function(int row, int column, String? value)? dropdownValidator,
  TextStyle? headerTextStyle,
  Color? headerBoxColor,
  TextStyle? cellTextStyle,
  TextStyle? hintTextStyle,
  TextStyle? errorTextStyle,
  TextInputType? textInputType,
  double? cellHeight,
  double? cellWidth,
})

Complete Example #

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

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Flutter Multi Table Example')),
        body: const SingleChildScrollView(child: MyHomePage()),
      ),
    );
  }
}

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

  @override
  MyHomePageState createState() => MyHomePageState();
}

class MyHomePageState extends State<MyHomePage> {
  late FlutterMultiTableController _controllerCreate;
  late FlutterMultiTableController _controllerSaved;
  late FlutterMultiTableConfig _create;
  late FlutterMultiTableConfig _saved;
  List<Map<String, String>> savedData = [];

  List<String> headers = [
    'No',
    'Name',
    'Age',
    'City',
    'Status',
  ];

  @override
  void initState() {
    super.initState();
    List<Map<String, String>> initialData = [
      {
        'No': '1',
        'Name': 'John',
        'Age': '',
        'City': 'New York',
        'Status': 'Active',
      },
      {
        'No': '2',
        'Name': 'Alice',
        'Age': '',
        'City': 'London',
        'Status': 'Inactive',
      },
    ];

    _controllerCreate = FlutterMultiTableController(
      initialData: initialData,
      headers: headers,
    );

    _controllerSaved = FlutterMultiTableController(
      initialData: const [],
      headers: headers,
    );
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();

    _create = FlutterMultiTableConfig(
      headers: headers,
      hint: '....',
      validator: (row, column, value) {
        if (column == 2 && (value.isEmpty)) {
          return 'Data wajib diisi';
        }
        return null;
      },
      dropdownValidator: (row, column, value) {
        if (column == 2 && (value == null || value.isEmpty)) {
          return 'Data wajib diisi';
        }
        return null;
      },
      headerTextStyle: const TextStyle(
        fontSize: 10,
        color: Colors.white,
        fontWeight: FontWeight.w700,
      ),
      errorTextStyle: const TextStyle(fontSize: 8, color: Colors.red),
      cellTextStyle: const TextStyle(
        fontSize: 6,
        fontWeight: FontWeight.w600,
      ),
      cellWidth: MediaQuery.of(context).size.width * 0.182,
      cellHeight: MediaQuery.of(context).size.height * 0.04,
      hintTextStyle: const TextStyle(
        fontSize: 8,
        fontWeight: FontWeight.w400,
      ),
      isReadOnly: (row, column) {
        if (column == 0 || column == 1 || column == 3 || column == 4) {
          return true;
        }
        return false;
      },
      isDropdown: (row, column) {
        if (column == 2 && (row != 1 && row != 13)) {
          return true;
        }
        return false;
      },
      dropdownOptions: ['Jakarta', 'New York', 'London', 'Tokyo', 'Paris'],
      onChanged: (row, column, value) {
        debugPrint('Changed: Row $row, Column $column, Value: $value');
      },
    );

    // Config untuk tabel saved data (semua cell readonly)
    _saved = FlutterMultiTableConfig(
      headers: headers,
      headerTextStyle: const TextStyle(
        fontSize: 10,
        color: Colors.white,
        fontWeight: FontWeight.w700,
      ),
      cellTextStyle: const TextStyle(
        fontSize: 6,
        fontWeight: FontWeight.w600,
      ),
      cellWidth: MediaQuery.of(context).size.width * 0.182,
      cellHeight: MediaQuery.of(context).size.height * 0.04,
      isReadOnly: (row, column) => true, // Semua cell readonly
    );
  }

  void _saveData() {
    // Get current table data from the controller
    final currentData = _controllerCreate.tableData.map((row) {
      // Convert TextEditingController values to String
      return row.map((key, value) {
        return MapEntry(key, value.text); // Extract text value
        // return MapEntry(key, value.toString());
      });
    }).toList();

    // Validate data before saving
    bool isValid = true;
    for (var row in currentData) {
      if (row['Age'] == null || row['Age']!.isEmpty) {
        isValid = false;
        break;
      }
    }

    if (!isValid) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(
          content: Text('Please fill all required fields'),
          backgroundColor: Colors.red,
        ),
      );
      return;
    }

    setState(() {
      savedData.addAll(currentData);
      // Update controller untuk saved table
      _controllerSaved = FlutterMultiTableController(
        initialData: savedData,
        headers: headers,
      );
    });

    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(
        content: Text('Data saved successfully'),
        backgroundColor: Colors.green,
      ),
    );
  }

  @override
  void dispose() {
    _controllerCreate.dispose();
    _controllerSaved.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          const Text(
            'Input Data',
            style: TextStyle(
              fontSize: 18,
              fontWeight: FontWeight.bold,
            ),
          ),
          const SizedBox(height: 10),
          FlutterMultiTable(
            controller: _controllerCreate,
            config: _create,
          ),
          const SizedBox(height: 20),
          Center(
            child: ElevatedButton(
              onPressed: _saveData,
              child: const Text('Submit'),
            ),
          ),
          if (savedData.isNotEmpty) ...[
            const SizedBox(height: 30),
            const Text(
              'Get Data',
              style: TextStyle(
                fontSize: 18,
                fontWeight: FontWeight.bold,
              ),
            ),
            const SizedBox(height: 10),
            FlutterMultiTable(
              controller: _controllerSaved,
              config: _saved,
            ),
          ],
        ],
      ),
    );
  }
}


License #

MIT

Contributing #

Pull requests are welcome.

5
likes
160
points
42
downloads

Publisher

verified publisheradpstore.my.id

Weekly Downloads

A Flutter packages for creating dynamic, multi-column tables with features like dropdowns, validation, and read-only cells. Ideal for interactive table inputs.

Repository (GitHub)
View/report issues

Topics

#table #tables #multi-table

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on flutter_multi_table