Flutter数据表格展示插件bs_flutter_datatable的使用

Flutter数据表格展示插件bs_flutter_datatable的使用

bs_flutter_datatable 是一个简单的插件,用于通过服务器端处理展示数据。以下是其功能:

  • 自定义样式
  • 可搜索的数据
  • 分页
  • 每页长度
  • 可排序
  • 服务器端处理

开始使用

pubspec.yaml 文件中添加依赖:

dependencies:
  ...
  bs_flutter_datatable: any

数据表格

示例代码可以在 这里 查看。

首先,导入必要的包:

import 'package:bs_flutter_datatable/bs_flutter_datatable.dart';

创建数据源:

class ExampleSource extends BsDatatableSource {
  static List<BsDataColumn> get columns => [
    BsDataColumn(label: Text('No'), orderable: false, searchable: false, width: 100.0),
    BsDataColumn(label: Text('Code'), columnName: 'typecd', width: 200.0),
    BsDataColumn(label: Text('Name'), columnName: 'typenm'),
  ];

  [@override](/user/override)
  BsDataRow getRow(int index) {
    return BsDataRow(index: index, cells: [
      BsDataCell(Text('${controller.start + index + 1}')),
      BsDataCell(Text('${response.data[index]['typecd']}')),
      BsDataCell(Text('${response.data[index]['typenm']}')),
    ]);
  }
}

定义行事件监听器:

class ExampleSource extends BsDatatableSource {
  ValueChanged<dynamic> onEditListener = (value) {};
  ValueChanged<dynamic> onDeleteListener = (value) {};

  [@override](/user/override)
  BsDataRow getRow(int index) {
    return BsDataRow(index: index, cells: [
      BsDataCell(Row(
        children: [
          TextButton(
            onPressed: () => onEditListener(response.data[index]['typeid']), 
            child: Container(child: Text('Edit'))
          ),
          TextButton(
            onPressed: () => onDeleteListener(response.data[index]['typeid']),
            child: Container(child: Text('Delete'))
          )
        ],
      ))
    ]);
  }
}

处理事件监听器:

Future loadApi(Map<String, dynamic> params) {
  return http.post(
    Uri.parse('http://localhost/flutter_crud/api/public/types/datatables'),
    body: params,
  ).then((value) {
    Map<String, dynamic> json = jsonDecode(value.body);
    setState(() {
      _source.response = BsDatatableResponse.createFromJson(json['data']);
      _source.onEditListener = (typeid) {
        /// 执行编辑操作
      };
      _source.onDeleteListener = (typeid) {
        /// 执行删除操作
      };
    });
  });
}

声明数据源和控制器:

class _MyAppState extends State<MyApp> {
  ExampleSource _source = ExampleSource();

  [@override](/user/override)
  void initState() {
    _source.controller = BsDatatableController();
    super.initState();
  }
}

创建表格视图:

BsDatatable(
  source: _source,
  title: Text('Datatables Data'),
  columns: ExampleSource.columns,
  serverSide: loadApi,
)

服务器端函数获取数据表响应:

Future loadApi(Map<String, dynamic> params) {
  return http.post(
    Uri.parse('http://localhost/flutter_crud/api/public/types/datatables'),
    body: params,
  ).then((value) {
    Map<String, dynamic> json = jsonDecode(value.body);
    setState(() {
      _source.response = BsDatatableResponse.createFromJson(json['data']);
      _source.onEditListener = (typeid) {
        /// 执行编辑操作
      };
      _source.onDeleteListener = (typeid) {
        /// 执行删除操作
      };
    });
  });
}

注意事项

在从服务器请求数据成功后,需要更新数据源的 response 数据:

Future loadApi(Map<String, dynamic> params) {
  return http.post(
    // ...
  ).then((value) {
    // ...
    setState(() {
      /// 更新数据源数据
      _source.response = BsDatatableResponse.createFromJson(json['data']);
      // ...
    });
  });
}

要重新加载数据,可以使用 reload 函数:

_source.controller.reload();

如果想直接显示来自 List 变量的数据,可以在构造函数中添加 data

class ExampleSource extends BsDatatableSource {
  ExampleSource({List? data}) : super(data: data);
  // ....
}

然后在你的小部件中设置 List 变量:

class Datatables extends StatefulWidget {
  [@override](/user/override)
  _DatatablesState createState() => _DatatablesState();
}

class _DatatablesState extends State<Datatables> {
  ExampleSource _source1 = ExampleSource(
    data: [
      {'typecd': 'TP1', 'typenm': 'Type 1'},
      {'typecd': 'TP2', 'typenm': 'Type 2'},
      {'typecd': 'TP3', 'typenm': 'Type 3'},
      {'typecd': 'TP4', 'typenm': 'Type 4'},
      {'typecd': 'TP5', 'typenm': 'Type 5'},
    ]
  );

  // ....
}

如果想动态添加数据,可以从按钮或其他方式调用 addaddAll 方法。如果想更新数据,调用 put 方法;如果想删除数据,调用 removeremoveAt 方法:

TextButton(
  onPressed: () {
    _source1.add({'typecd': 'TP1', 'typenm': 'Type ${_source1.datas.length}'});
  },
  child: Text('Add Row'),
)

完整示例代码

import 'dart:convert';

import 'package:bs_flutter_card/bs_flutter_card.dart';
import 'package:bs_flutter_datatable/bs_flutter_datatable.dart';
import 'package:bs_flutter_datatable_example/source.dart';
import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

void main() {
  runApp(MaterialApp(home: MyApp()));
}

class MyApp extends StatelessWidget {
  final _router = FluroRouter.appRouter;

  MyApp() {
    _router.define('/', handler: Handler(handlerFunc: (context, parameters) => Datatables()));
    _router.define('/test', handler: Handler(handlerFunc: (context, parameters) => Test()));
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Testing',
      debugShowCheckedModeBanner: false,
      initialRoute: '/',
      onGenerateRoute: _router.generator,
    );
  }
}

class Test extends StatelessWidget {
  final _router = FluroRouter.appRouter;

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        child: Column(
          children: [
            TextButton(
              onPressed: () => _router.navigateTo(context, '/'),
              child: Text('Test'),
            )
          ],
        ),
      ),
    );
  }
}

class Datatables extends StatefulWidget {
  [@override](/user/override)
  _DatatablesState createState() => _DatatablesState();
}

class _DatatablesState extends State<Datatables> {
  ExampleSource _source = ExampleSource(data: [
    {'typeid': 0, 'typecd': 'TP1', 'typenm': 'Type Baru'},
  ]);
  ExampleSource _source1 = ExampleSource(
      data: [
        {'typeid': 0, 'typecd': 'TP1', 'typenm': 'Type 1'},
        {'typeid': 0, 'typecd': 'TP2', 'typenm': 'Type 2'},
        {'typeid': 0, 'typecd': 'TP3', 'typenm': 'Type 3'},
        {'typeid': 0, 'typecd': 'TP4', 'typenm': 'Type 4'},
        {'typeid': 0, 'typecd': 'TP5', 'typenm': 'Type 5'},
      ],
      editListener: (value, index, sources, source) {
        final data = source.get(index);
        value['typenm'] = 'Edited';

        source.put(index, data);
      });

  [@override](/user/override)
  void initState() {
    _source.controller = BsDatatableController();
    super.initState();
  }

  Future loadApi(Map<String, dynamic> params) {
    return http
        .post(
      Uri.parse('http://localhost/flutter_crud/api/public/types/datatables'),
      body: params,
    )
        .then((value) {
      Map<String, dynamic> json = jsonDecode(value.body);
      setState(() {
        _source.response = BsDatatableResponse.createFromJson(json['data']);
        _source.onEditListener = (typeid, index, sources, source) {
          final data = _source.get(index);
          data['typenm'] = 'Edited';

          _source.put(index, data);
        };
        _source.onDeleteListener = (typeid, index, sources, source) {
          source.removeAt(index);
        };
      });
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Flutter Datatables.net'),
        ),
        body: Scrollbar(
          child: SingleChildScrollView(
            child: Container(
              padding: EdgeInsets.all(20.0),
              child: BsCard(
                children: [
                  BsCardContainer(title: Text('Datatables'), actions: [
                    Container(
                      margin: EdgeInsets.only(right: 5.0),
                      child: TextButton(
                        onPressed: () {
                          _source.insert(0, {
                            'typecd': 'TP1',
                            'typenm': 'Type ${_source.response.countData + 1}'
                          });
                        },
                        child: Text('Insert'),
                      ),
                    ),
                    TextButton(
                      onPressed: () {
                        _source.add({
                          'typecd': 'TP1',
                          'typenm': 'Type ${_source.response.countData + 1}'
                        });
                      },
                      child: Text('Add'),
                    )
                  ]),
                  BsCardContainer(
                    child: BsDatatable(
                      source: _source,
                      clearData: BsDatatablesClearData.never,
                      title: Text('Datatables Data'),
                      columns: ExampleSource.columns,
                      language: BsDatatableLanguage(
                          nextPagination: 'Next',
                          previousPagination: 'Previous',
                          information: 'Show __START__ to __END__ of __FILTERED__ entries',
                          informationFiltered: 'filtered from __DATA__ total entries',
                          firstPagination: 'First Page',
                          lastPagination: 'Last Page',
                          hintTextSearch: 'Search data ...',
                          perPageLabel: null,
                          searchLabel: null),
                      serverSide: loadApi,
                    ),
                  ),
                  BsCardContainer(
                    actions: [
                      Container(
                        margin: EdgeInsets.only(right: 5.0),
                        child: TextButton(
                          onPressed: () {
                            _source1.insert(0, {
                              'typecd': 'TP1',
                              'typenm': 'Type ${_source1.response.countData + 1}'
                            });
                          },
                          child: Text('Insert'),
                        ),
                      ),
                      TextButton(
                        onPressed: () {
                          _source1.add({
                            'typecd': 'TP1',
                            'typenm': 'Type ${_source1.response.countData + 1}'
                          });
                        },
                        child: Text('Add'),
                      )
                    ],
                    child: BsDatatable(
                      source: _source1,
                      title: Text('Datatables Data'),
                      columns: ExampleSource.columns,
                    ),
                  )
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

更多关于Flutter数据表格展示插件bs_flutter_datatable的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter数据表格展示插件bs_flutter_datatable的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何使用 bs_flutter_datatable 插件在 Flutter 中展示数据表格的示例代码。bs_flutter_datatable 是一个用于在 Flutter 中展示数据表格的插件,支持分页、排序和搜索等功能。

首先,确保你已经在 pubspec.yaml 文件中添加了 bs_flutter_datatable 依赖:

dependencies:
  flutter:
    sdk: flutter
  bs_flutter_datatable: ^x.y.z  # 请使用最新版本号

然后,运行 flutter pub get 以获取依赖。

接下来是一个完整的 Flutter 应用示例,展示如何使用 bs_flutter_datatable

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter DataTable Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: DataTableScreen(),
    );
  }
}

class DataTableScreen extends StatefulWidget {
  @override
  _DataTableScreenState createState() => _DataTableScreenState();
}

class _DataTableScreenState extends State<DataTableScreen> {
  final List<Map<String, dynamic>> data = [
    {"name": "Alice", "age": 24, "email": "alice@example.com"},
    {"name": "Bob", "age": 30, "email": "bob@example.com"},
    {"name": "Charlie", "age": 22, "email": "charlie@example.com"},
    // 添加更多数据以测试分页功能
  ];

  final List<DataTableColumn> columns = [
    DataTableColumn(
      label: "Name",
      fieldName: "name",
      isSortable: true,
      isVisible: true,
    ),
    DataTableColumn(
      label: "Age",
      fieldName: "age",
      isSortable: true,
      isVisible: true,
    ),
    DataTableColumn(
      label: "Email",
      fieldName: "email",
      isSortable: true,
      isVisible: true,
    ),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("DataTable Example"),
      ),
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: BsFlutterDataTable(
          columns: columns,
          rows: data,
          rowCountPerPage: 2,  // 每页行数
          showSearch: true,    // 是否显示搜索框
          onRowClick: (rowData) {
            // 点击行时的回调
            print("Clicked row: $rowData");
          },
        ),
      ),
    );
  }
}

在这个示例中:

  1. MyApp 类是应用程序的入口点。
  2. DataTableScreen 类是一个有状态的组件,用于展示数据表格。
  3. data 列表包含了表格中的数据,每个元素是一个 Map,表示一行数据。
  4. columns 列表定义了表格的列,包括标签、字段名、是否可排序和是否可见。
  5. BsFlutterDataTable 组件用于渲染数据表格,支持分页和搜索功能。

运行这个应用,你将看到一个带有分页和搜索功能的数据表格。点击表格中的某一行时,会在控制台打印出被点击行的数据。

请确保你已经正确配置了 bs_flutter_datatable 插件,并根据需要调整示例代码中的数据和列定义。

回到顶部