Toxic
Toxic

Reputation: 105

ReorderableSliverList with Futurebuilder

I'm trying to populate a ReorderableSliverList with data from an API using FutureBuilder.

Model (RouteOrderTable)

 RouteOrderTable(
      {required this.deliveryPeriod,
      required this.driverId,
      required this.processId,
      required this.routeId,
      required this.routeLines,
      required this.status,
      required this.vanId});


  RouteOrderTable.fromJson(Map<String, dynamic> json) {
    deliveryPeriod = json['deliveryPeriod'];
    driverId = json['driverId'];
    processId = json['processId'];
    routeId = json['routeId'];
    if (json['routeLines'] != null) {
      routeLines = <RouteOrderLine>[];
      json['routeLines'].forEach((v) {
        routeLines!.add(new RouteOrderLine.fromJson(v));
      });
    }
    status = json['status'];
    vanId = json['vanId'];
  }

Model (RouteOrderLine)

  RouteOrderLine(
      {required this.city,
      required this.custAccount,
      required this.custName,
      required this.invoiceId,
      required this.deliveryDate,
      required this.productType,
      required this.routeId,
      required this.salesId,
      required this.volume,
      required this.weight});

  RouteOrderLine.fromJson(Map<String, dynamic> json) {
    city = json['city'];
    custAccount = json['custAccount'];
    custName = json['custName'];
    deliveryDate = DateTime.tryParse(json['deliveryDate']);
    invoiceId = json['invoiceId'];
    productType = json['productType'];
    routeId = json['routeId'];
    salesId = json['salesId'];
    volume = json['volume'];
    weight = json['weight'];
  }

JSON Data

[
    {
        "deliveryPeriod": 1,
        "driverId": "",
        "processId": "PRO000475",
        "routeId": "ROU001804",
        "routeLines": [
            {
                "city": "Naxxar",
                "custAccount": "CUST010917",
                "custName": "",
                "deliveryDate": "2021-07-06T12:00:00",
                "invoiceId": "",
                "productType": 0,
                "routeId": "ROU001804",
                "salesId": "SO002496",
                "volume": 0.011113889,
                "weight": 8.700435
            }
        ],
        "status": 10,
        "vanId": "TFI 943"
    },
    {
        "deliveryPeriod": 2,
        "driverId": "",
        "processId": "PRO000475",
        "routeId": "ROU001805",
        "routeLines": [
            {
                "city": "Birkirkara",
                "custAccount": "CUST010916",
                "custName": "",
                "deliveryDate": "2021-07-06T12:00:00",
                "invoiceId": "",
                "productType": 0,
                "routeId": "ROU001805",
                "salesId": "SO002497",
                "volume": 0.005556111,
                "weight": 4.349565
            }
        ],
        "status": 30,
        "vanId": "HBA 804"
    }
]

Screen - One of the issues here is that I cannot use removeAt() and insert() for the onReorder() because they aren't defined for the type Future.


class _SliverScreenState extends State<SliverScreenState> {
  late Future<List<RouteOrderTable>> futureRouteTable;

  @override
  void initState() {
    super.initState();
    futureRouteTable = fetchData();
  }

  @override
  Widget build(BuildContext context) {
    void _onReorder(int oldIndex, int newIndex) {
    /*   setState(() {
        Widget row = futureRouteTable!.removeAt(oldIndex);
        futureRouteTable.insert(newIndex, row);
      });*/
    }

    ScrollController _scrollController =
        PrimaryScrollController.of(context) ?? ScrollController();
    final someOtherSliver = SliverToBoxAdapter();

    return  FutureBuilder<List<RouteOrderTable>>(
        future: futureRouteTable,
        builder: (context, snapshot) {

    Widget routeOrderListSliver;
    final List<RouteOrderTable>? posts = snapshot.data;
    if (snapshot.hasData) {
      routeOrderListSliver = CustomScrollView(
        controller: _scrollController,
        slivers: <Widget>[
          SliverAppBar(
            flexibleSpace: FlexibleSpaceBar(
              title: Text('ROUTE NO'),
            ),
          ),
          ReorderableSliverList(
            delegate: SliverChildBuilderDelegate(
              (context, index) => ListTile(
                title: Text(posts![index].routeId.toString(),
                style: TextStyle(fontSize: 20.0),),
              ),
          childCount: posts!.length,
          ),
        onReorder: _onReorder,
        ),
      ],
    );
    }else {
    routeOrderListSliver = Center(child: SliverToBoxAdapter(child: CircularProgressIndicator(),));
    }

    return CustomScrollView(
    slivers: <Widget>[
      someOtherSliver,
    routeOrderListSliver
    ],
    );
    },
          );
  }
}

FetchData


Future<List<RouteOrderTable>> fetchData() async {
  final response =
      await http.get(Uri.parse('https://10.0.2.2:7038/api/route/1?siteId=1'));

  try {
    if (response.statusCode == 200) {

      List<RouteOrderTable> lstRouteOrderTable = [];

      Iterable l = jsonDecode(response.body);
      lstRouteOrderTable = List<RouteOrderTable>.from(l.map((model) => RouteOrderTable.fromJson(model)));
      return lstRouteOrderTable;
    } else {

      throw Exception('Failed to load route');
    }
  } catch (e) {
    print(e);
  }
  return new List<RouteOrderTable>.empty();
}

ListView.builder


ListView _buildRouteOrderTable(
    BuildContext context, List<RouteOrderTable>? lstRouteTable) {
  return ListView.builder(
    itemCount: lstRouteTable == null ? 0 : lstRouteTable.length,
    //padding: EdgeInsets.all(8),
    itemBuilder: (context, index) {
      return Card(
        elevation: 4,
        child: ListTile(
          title: Text(
            lstRouteTable == null ? "" : lstRouteTable[index].routeId.toString(),
            style: TextStyle(fontWeight: FontWeight.bold),
          ),
          subtitle: Text(
              lstRouteTable == null ? "" : lstRouteTable[index].processId.toString()),
        ),
      );
    },
  );
}

Upvotes: 1

Views: 104

Answers (1)

Advait
Advait

Reputation: 599

You can define the _onReorder function inside the FutureBuilder and then use the snapshot to create a variable of RouteOrderTable.

This will give you access to the removeAt & insert functions.

There are two ways of doing this.

final List<RouteOrderTable>? posts = snapshot.data;

if (snapshot.hasData) {

  void _onReorder(int oldIndex, int newIndex){
    //1. Define the function here and then pass it as a parameter.
  }

  routeOrderListSliver = CustomScrollView(
    controller: _scrollController,
    slivers: <Widget>[
      SliverAppBar(
        flexibleSpace: FlexibleSpaceBar(
          title: Text('ROUTE NO'),
        ),
      ),
      ReorderableSliverList(
        delegate: SliverChildBuilderDelegate(
          (context, index) => ListTile(
            title: Text(posts![index].routeId.toString(),
            style: TextStyle(fontSize: 20.0),),
          ),
      childCount: posts!.length,
      ),
    onReorder: (int oldIndex, int newIndex){
       
       // OR
       // 2. You can directly create the function here.

      },
    ),
  ],
);
}

Both ways, you get access to the posts variable where you can do your operations.

Upvotes: 1

Related Questions