Search code examples
jsonflutterrestdartflutter-http

How to sort a Future<List> data type on DataTable widget in Flutter?


I have a problem for sorting a list from Future data type in DataTable widget

class User {
  final String idUser,
  name,
  phone;

  User(
    {this.idUser,
    this.name,
    this.phone});

  factory User.fromJson(Map<String, dynamic> json) {
    return User(
    idUser: json['_id'],
    name: json['name'],
    phone: json['phone']);
  }
}

List<User> userFromJson(jsonData) {
  List<User> result =
    List<User>.from(jsonData.map((item) => User.fromJson(item)));

  return result;
}

// index
Future<List<User>> fetchUser() async {
  String route = AppConfig.API_ENDPOINT + "userdata";
  final response = await http.get(route);
  if (response.statusCode == 200) {
    var jsonResp = json.decode(response.body);

    return userFromJson(jsonResp);
  } else {
    throw Exception('Failed load $route, status : ${response.statusCode}');
  }
}

I wan't to call it on DataTable widget inside a FutureBuilder widget

int sortColumnIndex=0;
bool isAscending = true;
bool sort=false;
Future<List<User>> user;
User = fetchUser();

@override
  Widget build(BuildContext context) {
     return FutureBuilder(
        future: user,
        builder: (context, snapshot) {
          if(!snapshot.hasData) {
            return Center(child: CircularProgressIndicator());
          }

          if(snapshot.hasData) {
            return Column(
              mainAxisSize: MainAxisSize.min,
              mainAxisAlignment: MainAxisAlignment.center,
              verticalDirection: VerticalDirection.down,
              children: <Widget>[
                // Table
                Expanded(
                  child: ListView(
                    children: [
                      Container(
                        padding: EdgeInsets.all(5),
                        child: dataBody(snapshot.data)
                      ),
                    ],
                  ),
                ),                  
              ],
            );
          }
          return Center();            
        },
      );
    }

The dataBody function is:

SingleChildScrollView dataBody(List<User> listUser) {
  return SingleChildScrollView(
    scrollDirection: Axis.horizontal,
    child: DataTable(
      sortAscending: isAscending,
      sortColumnIndex: sortColumnIndex,
      showCheckboxColumn: false,
      columns: [
        DataColumn(
          label: Text("Name"),
          numeric: false,
          tooltip: "Name",
          onSort: (columnIndex, ascending) { 
            setState(() {sort = !sort;
            });
            onSortColumn(columnIndex, ascending);
          }),
        DataColumn(
            label: Text("Phone"),
            numeric: false,
            tooltip: "Phone"
        ),       
    ],
    
    rows: listUser
      .map(
        (user) => DataRow(
        onSelectChanged: (b) {
          print(user.name);
        },
        cells: [
          DataCell(
              Text(user.name)
          ),
          DataCell(
              Text(user.phone)
          ),
        ]),
      ).toList(),
    ),
  );
}

while the onSortColumn function is like this:

onSortColumn(int columnIndex, bool ascending) {
  if (columnIndex == 0) {
    if (ascending) {
      user.sort((a, b) => a.name.compareTo(b.name));
    } else {
      user.sort((a, b) => b.name.compareTo(a.name));
    }
  }
}

it just like the word "sort" in "onSortColumn" turn out underlined red and give a message like this:

The method 'sort' isn't defined for the type 'Future'. Try correcting the name to the name of an existing method, or defining a method named 'sort'.

if there are another ways to sorting, please let me know, thank you very much


Solution

  • int sortColumnIndex=0;
    bool isAscending = true;
    bool sort=false;
    Future<List<User>> userList;
    List<User> users;
    User = fetchUser();
    
    @override
     Widget build(BuildContext context) {
       return FutureBuilder(
         future: userList,
         builder: (context, snapshot) {
           if(!snapshot.hasData) {
             return Center(child: CircularProgressIndicator());
           }
    
           if(snapshot.hasData) {
              users = snapshot.data;
              return Column(
                mainAxisSize: MainAxisSize.min,
                mainAxisAlignment: MainAxisAlignment.center,
                verticalDirection: VerticalDirection.down,
                children: <Widget>[
                // Table
                Expanded(
                  child: ListView(
                    children: [
                      Container(
                        padding: EdgeInsets.all(5),
                        child: dataBody(users)
                      ),
                    ],
                  ),
                ),                  
              ],
            );
          }
          return Center();            
        },
      );
    }
    

    Then for sorting function

    onSortColumn(int columnIndex, bool ascending) {
      if (columnIndex == 0) {
        if (ascending) {
          users.sort((a, b) => a.name.compareTo(b.name));
        } else {
          users.sort((a, b) => b.name.compareTo(a.name));
        }
      }
    }