본문 바로가기
Flutter

03. Fultter Datatable 사용

by NaHyungMin 2022. 9. 7.

거래처 datatable을 만들고 싶음.

국내 사이트에선 정보가 없고, 해외 사이트에선 밑단 service가 아닌 screen에서 처리하는 샘플만 봄.

그래서 4시간 동안 서치하고 변경한 정보를 공유 차 올림.

pub

syncfusion_flutter_datagrid: ^20.2.46

 

Customers

import 'package:flutter/material.dart';
import 'package:simple/datagrid/customer_datagrid.dart';
import 'package:simple/model/customer/customer_model.dart';
import 'package:simple/services/customer/customer_service.dart';
import 'package:syncfusion_flutter_datagrid/datagrid.dart';

class Customers extends StatefulWidget {
  const Customers({Key? key}) : super(key: key);

  @override
  State<Customers> createState() => _CustomersState();
}

class _CustomersState extends State<Customers> {
  late final CustomerService customerService;
  late final CustomerDatagrid customerDatagrid;

  @override
  Widget build(BuildContext context) {
    //https://stackoverflow.com/questions/49986303/flutter-how-to-add-a-header-row-to-a-listview
    //https://api.flutter.dev/flutter/material/DataTable-class.html
    //https://stackoverflow.com/questions/60644375/flutter-datatable-multiline-wrapping-and-centering
    //https://www.syncfusion.com/kb/12646/how-to-populate-flutter-datatable-sfdatagrid-with-json-api

    customerService = CustomerService(context);
    return Scaffold(
      body: FutureBuilder(
          future: generateCustomerList(),
          builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
            return _getData(snapshot);
          }),
    );
  }

  Future generateCustomerList() async {
    List<CustomerModel> customerModelList = await customerService.getCustomerList() as List<CustomerModel>;
    customerDatagrid = CustomerDatagrid(customerModelList);
    customerDatagrid.customerModelList = customerModelList;
  }

  Widget _getData(AsyncSnapshot<dynamic> snapshot) {
    return snapshot.connectionState == ConnectionState.done
        ? SfDataGrid(
        source: customerDatagrid,
        columns: customerDatagrid.getColumns())
        : const Center(
            child: CircularProgressIndicator(
            strokeWidth: 3,
          ),
      );
  }
}

 

CustomerService

import 'package:flutter/material.dart';
import 'package:simple/commons/text/text_information.dart';
import 'package:simple/model/customer/customer_model.dart';
import 'package:simple/model/http/http_header_model.dart';
import 'package:simple/utils/dialog/custom_dialog.dart';
import 'package:simple/utils/dialog/dialog_action.dart';

import 'package:simple/utils/http/http_request.dart';
import 'package:simple/utils/http/http_url.dart';

import 'package:simple/model/customer/customer_model_list.dart';

class CustomerService {
  final BuildContext context;

  CustomerService(this.context);

  void add(CustomerModel customerModel) {
    CustomDialog.confirm(context, title: '저장 확인', content: '입력한 정보로 거래처를 저장하시겠습니까?'
        , positive: DialogAction('확인', () => _add(customerModel))
        , negative: DialogAction('취소',  () => true));
  }

  bool _add(CustomerModel customerModel) {
    HttpHeaderModel httpHeaderModel = HttpHeaderModel();
    httpHeaderModel.transactionNumber = "1000";
    final result = HttpRequest.fetchPost<CustomerModel>(HttpUrl.customerAdd, httpHeaderModel, customerModel);

    result.then((value) => {
      if(value == null) {
        CustomDialog.confirm(context, title: '거래처 등록', content: TextInformation.serverConnectionFailed, positive: DialogAction('확인', () => true))
      } else if(!value.status) {
        CustomDialog.confirm(context, title: '거래처 등록', content: '거래처 등록에 실패하였습니다. 사유 : ${value?.error.errorMessage}', positive: DialogAction('확인', () => true))
      } else {
        if(value.status) {
          CustomDialog.confirm(context, title: '거래처 등록', content: '거래처 등록에 완료되었습니다.', positive: DialogAction('확인', () => true)),
        }
      }
    });

    return true;
  }

  Future getCustomerList() async {
    HttpHeaderModel httpHeaderModel = HttpHeaderModel();
    httpHeaderModel.transactionNumber = "1000";
    final result = HttpRequest.fetchPostNoBody(HttpUrl.customerList, httpHeaderModel);
    CustomerModelList customerModelList = CustomerModelList(customerModelList: <CustomerModel>[]);

    var bb = await result.then((value) => {
      if(value == null) {
        CustomDialog.confirm(context, title: '거래처 리스트', content: TextInformation.serverConnectionFailed, positive: DialogAction('확인', () => true))
      } else if(!value.status) {
        CustomDialog.confirm(context, title: '거래처 리스트', content: '거래처 리스트를 불러오는데 실패했습니다. 사유 : ${value?.error.errorMessage}', positive: DialogAction('확인', () => true))
      } else {
        if(value.status) {
          customerModelList = CustomerModelList.fromJson(value.data),
        }
      }
    });

    return customerModelList.customerModelList;
  }

  bool _addConfirmDialog() {
    return true;
  }
}

 

CustomerDatagrid

 

import 'package:flutter/material.dart';
import 'package:simple/model/customer/customer_model.dart';
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
//import 'package:intl/intl.dart';

class CustomerDatagrid extends DataGridSource {
//https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html
//https://pub.dev/packages/syncfusion_flutter_datagrid
//https://help.syncfusion.com/flutter/datagrid/getting-started
  CustomerDatagrid(this.customerModelList) {
    buildDataGridRow();
  }

  List<DataGridRow> dataGridRows = [];
  List<CustomerModel> customerModelList = [];

  @override
  List<DataGridRow> get rows => dataGridRows;

  void buildDataGridRow() {
    dataGridRows = customerModelList.map<DataGridRow>((dataGridRow) {
      return DataGridRow(cells: [
        DataGridCell<String>(columnName: 'name', value: dataGridRow.name),
        DataGridCell<String>(
            columnName: 'number', value: dataGridRow.number),
        DataGridCell<String>(
            columnName: 'registrationNumber', value: dataGridRow.registrationNumber),
        DataGridCell<String>(
            columnName: 'conditions', value: dataGridRow.conditions),
        DataGridCell<String>(columnName: 'type', value: dataGridRow.type),
      ]);
    }).toList(growable: false);
  }

  @override
  DataGridRowAdapter buildRow(DataGridRow row) {
    return DataGridRowAdapter(cells: [
      Container(
        alignment: Alignment.center,
        padding: const EdgeInsets.all(8.0),
        child: Text(
          row.getCells()[0].value.toString(),
          overflow: TextOverflow.ellipsis,
        ),
      ),
      Container(
        alignment: Alignment.center,
        padding: const EdgeInsets.all(8.0),
        child: Text(
          row.getCells()[1].value,
          overflow: TextOverflow.ellipsis,
        ),
      ),
      Container(
        alignment: Alignment.center,
        padding: const EdgeInsets.all(8.0),
        child: Text(
          row.getCells()[2].value.toString(),
          overflow: TextOverflow.ellipsis,
        ),
      ),
      Container(
        alignment: Alignment.center,
        padding: const EdgeInsets.all(8.0),
        child: Text(
          //DateFormat('MM/dd/yyyy').format(row.getCells()[3].value).toString(),
          row.getCells()[3].value.toString(),
          overflow: TextOverflow.ellipsis,
        ),
      ),
      Container(
        alignment: Alignment.center,
        padding: const EdgeInsets.all(8.0),
        child: Text(
          row.getCells()[4].value.toString(),
          overflow: TextOverflow.ellipsis,
        ),
      ),
    ]);
  }

  List<GridColumn> getColumns() {
    return <GridColumn>[
      GridColumn(
          columnName: 'name',
          label: Container(
              padding: const EdgeInsets.all(16.0),
              alignment: Alignment.center,
              child: const Text('name',))),
      GridColumn(
          columnName: 'number',
          label: Container(
              padding: const EdgeInsets.all(16.0),
              alignment: Alignment.center,
              child: const Text('number'))),
      GridColumn(
          columnName: 'registrationNumber',
          width: 120,
          label: Container(
              padding: const EdgeInsets.all(16.0),
              alignment: Alignment.center,
              child: const Text('registrationNumber'))),
      GridColumn(
          columnName: 'conditions',
          label: Container(
              padding: const EdgeInsets.all(16.0),
              alignment: Alignment.center,
              child: const Text('conditions'))),
      GridColumn(
          columnName: 'type',
          label: Container(
              padding: const EdgeInsets.all(16.0),
              alignment: Alignment.center,
              child: const Text('type'))),
    ];
  }
}

 

 

테스트 용으로 서버에서 받아온 데이터라 정상적인 데이터 입력 시 매핑됨.

 

* 매핑 변경

@override
DataGridRowAdapter buildRow(DataGridRow row) {
  return DataGridRowAdapter(
      cells: row.getCells().map<Widget>((dataGridCell) {
        return Container(
            alignment: (dataGridCell.columnName == 'id' ||
                dataGridCell.columnName == 'salary')
                ? Alignment.centerRight
                : Alignment.centerLeft,
            padding: const EdgeInsets.symmetric(horizontal: 16.0),
            child: Text(
              dataGridCell.value.toString(),
              overflow: TextOverflow.ellipsis,
            ));
      }).toList());
}

 

List<GridColumn> getColumns() {
  return <GridColumn>[
    customGridColumn.getCustomGridColumn("name", "상호", alignment: Alignment.center),
    customGridColumn.getCustomGridColumn("number", "사업자번호", alignment: Alignment.center),
    customGridColumn.getCustomGridColumn("registrationNumber", "법인 등록번호", alignment: Alignment.center, width: 150),
    customGridColumn.getCustomGridColumn("conditions", "업태"),
    customGridColumn.getCustomGridColumn("ceoName", "종목"),
    customGridColumn.getCustomGridColumn("conditions", "대표자 성명"),
    customGridColumn.getCustomGridColumn("address", "회사 주소"),
    customGridColumn.getCustomGridColumn("phoneNumber", "전화번호", width: 120),
    customGridColumn.getCustomGridColumn("faxNumber", "팩스번호"),
    customGridColumn.getCustomGridColumn("cellNumber", "휴대폰"),
    customGridColumn.getCustomGridColumn("email", "이메일"),
    customGridColumn.getCustomGridColumn("bankName", "은행명"),
    customGridColumn.getCustomGridColumn("bankOwnerName", "예금주"),
    customGridColumn.getCustomGridColumn("bankAccountNumber", "계좌번호"),
  ];
}

 


class CustomGridColumn {
  //https://flutterrdart.com/dart-optional-default-parameters-function/
  GridColumn getCustomGridColumn(String columnName, String text, { Alignment alignment = Alignment.center, int width = -1 }) {
    double? columnWidth = width > 0 ? width as double : null;

    if(columnWidth != null) {
      return _getCustomGridColumnWidth(columnName, text, alignment, columnWidth);
    } else {
      return GridColumn(
          columnName: columnName,
          label: Container(
            padding: const EdgeInsets.all(16.0),
            alignment: alignment,
            child: Text(text),
          )
      );
    }
  }

  GridColumn _getCustomGridColumnWidth(String columnName, String text, Alignment alignment, double width) {
    return GridColumn(
        columnName: columnName,
        width: width,
        label: Container(
          padding: const EdgeInsets.all(16.0),
          alignment: alignment,
          child: Text(text),
        )
    );
  }
}

'Flutter' 카테고리의 다른 글

06. Flutter Future build 이벤트 방지  (0) 2022.09.19
05. Flutter build 종료 후 이벤트  (0) 2022.09.16
04. Flutter 상태 저장 shared_preferences  (0) 2022.09.16
02. Flutter Dio 사용법  (0) 2022.08.28
01. 플러터 설치  (0) 2021.07.26