Dan530c
Dan530c

Reputation: 457

Sort JSON in alphabetical order - Flutter

I'd like to be able to return my profileList to my ListView in alphabetical order.

I have my "All people" class which has a ListView widget using the json and creating a list of people.

The code below is from my All People class where I'm fetching the json.

class AllPeople extends StatefulWidget {
final String title;

AllPeople(this.title);

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

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
  title: Text("Listviews"),
),
);
}

class AllPeopleState extends State<AllPeople> {
 List data;
 List<Profile> profiles;

 Future<String> getData() async {
 var response = await http.get(
    Uri.encodeFull("http://test.mallcomm.co.uk/json_feeds/users.json"),
    headers: {"Accept": "application/json"});

  fetchPeople().then((List<Profile> p) {
    this.setState(() {
    data = json.decode(response.body);
    profiles = p;
  });
});

return "Success!";
}

@override
void initState() {
  this.getData();
}

 @override
 Widget build(BuildContext context) {
  return Scaffold(
  appBar: AppBar(
    title: Text('CMS Users'),
  ),
  body: ListView.builder(
      padding: EdgeInsets.only(top: 20.0, left: 4.0),
      itemExtent: 70.0,
      itemCount: data == null ? 0 : data.length,
      itemBuilder: (BuildContext context, int index) {
        return Card(
          elevation: 10.0,
          child: InkWell(
            onTap: () {
              Navigator.push(
                  context,
                  new MaterialPageRoute(
                    builder: (BuildContext context) =>
                        new PeopleDetails("Profile Page", profiles[index]),
                  ));
            },
            child: ListTile(
              leading: CircleAvatar(
                child: Text(profiles[index].getInitials()),
                backgroundColor: Colors.deepPurple,
                radius: 30.0,
              ),
              title: Text(
                  data[index]["firstname"] + "." + data[index]["lastname"]),
              subtitle: Text(
                  data[index]["email"] + "\n" + data[index]["phonenumber"]),
            ),
          ),
        );
      }),
  );
  }
 }

Future<List<Profile>> fetchPeople() async {
 try {
 http.Response response =
    await http.get('http://test.mallcomm.co.uk/json_feeds/users.json');

 List<dynamic> responseJson = json.decode(response.body);

 List<Profile> profileList =
    responseJson.map((d) => new Profile.fromJson(d)).toList();

profileList.sort((a, b) {
  return a.lastName.toLowerCase().compareTo(b.lastName.toLowerCase());
});

  return profileList;
} catch (e) {
print(e.toString());
}
return null;
}

I then have my "User profile" class which is storing my json Profile

class Profile {
 final String firstName;
 final String lastName;
 final String phoneNumber;
 final String userEmail;

bool verifiedValue = false;
bool approvedValue = false;
bool securityApprovedValue = false;
bool blockedValue = false;

Profile({this.firstName, this.lastName, this.phoneNumber, this.userEmail});

factory Profile.fromJson(Map<String, dynamic> json) {
  return new Profile(
  firstName: json["firstname"],
  lastName: json["lastname"],
  phoneNumber: json["phonenumber"],
  userEmail: json["email"],
  );
 }

I've tried to do something like

 profileList.sort((a,b) {
return a.lastName.toLowerCase().compareTo(b.lastName.toLowerCase());
 });

just before I return profileList but it didn't work. I've tried looking at some different examples but If i'm honest I don't understand it too well.

Upvotes: 1

Views: 9827

Answers (1)

Richard Heap
Richard Heap

Reputation: 51751

The sort function you suggested does seem to work as you'd expect (but, of course, only compares last name - you might want to compare first name if the last names are equal). I tidied up a bit, to produce this working example:

import 'dart:convert';
import 'dart:async';

import 'package:http/http.dart' as http;

main() async {
  fetchPeople().then((list) {
    list.forEach(print);
  });
}

Future<List<Profile>> fetchPeople() async {
  try {
    http.Response response =
        await http.get('http://test.mallcomm.co.uk/json_feeds/users.json');

    List<dynamic> responseJson = json.decode(response.body);

    List<Profile> profileList =
        responseJson.map((d) => new Profile.fromJson(d)).toList();

    profileList.sort((a, b) {
      return a.lastName.toLowerCase().compareTo(b.lastName.toLowerCase());
    });

    return profileList;
  } catch (e) {
    print(e.toString());
  }
}

class Profile {
  final String firstName;
  final String lastName;
  final String phoneNumber;
  final String userEmail;

  bool verifiedValue = false;
  bool approvedValue = false;
  bool securityApprovedValue = false;
  bool blockedValue = false;

  Profile({this.firstName, this.lastName, this.phoneNumber, this.userEmail});

  factory Profile.fromJson(Map<String, dynamic> json) {
    return new Profile(
      firstName: json["firstname"],
      lastName: json["lastname"],
      phoneNumber: json["phonenumber"],
      userEmail: json["email"],
    );
  }

  @override
  String toString() {
    return 'Profile: $firstName $lastName';
  }
}

Here's a State example that works.

class _MyHomePageState extends State<MyHomePage> {
  List<Profile> profiles = [];

  @override
  void initState() {
    super.initState();
    _refresh();
  }

  void _refresh() {
    fetchPeople().then((list) {
      setState(() {
        profiles = list;
      });
    });
  }

  Future<List<Profile>> fetchPeople() async {
    try {
      http.Response response =
      await http.get('http://test.mallcomm.co.uk/json_feeds/users.json');

      List<dynamic> responseJson = json.decode(response.body);

      List<Profile> profileList =
      responseJson.map((d) => new Profile.fromJson(d)).toList();

      profileList.sort((a, b) {
        return a.lastName.toLowerCase().compareTo(b.lastName.toLowerCase());
      });

      return profileList;
    } catch (e) {
      print(e.toString());
      return [];
    }
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new ListView.builder(
        itemBuilder: (context, i) => new Text('${profiles[i].firstName} ${profiles[i].lastName}'),
        itemCount: profiles.length,
      ),
    );
  }
}

Upvotes: 4

Related Questions