I have a problem to load a list from a class that the class need data from several database
The database:
A. userdata (_id, name, phone)
B. mariage status (_id, userID, mariageStatus)
--> "_id" in userdata & "userID" in marriage status are thing to be matched
read the userdata:
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}');
}
}
while to read the marriage:
class Marriage{
final String idUser, mariageStatus;
Marriage(
{this.idUser,
this.mariageStatus});
factory Marriage.fromJson(Map<String, dynamic> json) {
return Marriage(
idUser: json['userID'],
name: json['mariageStatus']);
}
}
List<Marriage> marriageFromJson(jsonData) {
List<Marriage> result =
List<Marriage>.from(jsonData.map((item) => Marriage.fromJson(item)));
return result;
}
// index
Future<List<Marriage>> fetchMarriage() async {
String route = AppConfig.API_ENDPOINT + "marriage";
final response = await http.get(route);
if (response.statusCode == 200) {
var jsonResp = json.decode(response.body);
return marriageFromJson(jsonResp);
} else {
throw Exception('Failed load $route, status : ${response.statusCode}');
}
}
then how to make a list off combination class like this?
class User_Mariage {
final String idUser,
name,
phone,
mariageStatus;
User(
{this.idUser,
this.name,
this.phone,
this.mariageStatus});
factory User.fromJson(Map<String, dynamic> json) {
return User(
idUser:
name:
phone:
mariageStatus:
}
}
List<User> userFromJson(jsonData) {
List<User> result =
List<User>.from(jsonData.map((item) => User.fromJson(item)));
return result;
}
of if there are another better way to make the list, please let me know, thank you very much
For me it looks like you are using the wrong database query. Maybe there is a possibility to use foreign keys (userId).
There are different approaches to combine the data.
Here is one example, where you could combine classes by reference and use getter
Your original User class:
import 'dart:convert';
class User {
final String id, name, phone;
User({
required this.id,
required this.name,
required this.phone,
});
factory User.fromJson(Map<String, dynamic> json) {
return User(id: json['_id'], name: json['name'], phone: json['phone']);
}
}
List<User> userFromJson(dynamic jsonData) {
return List<User>.from(jsonData.map((item) => User.fromJson(item)));
}
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}');
}
}
Your original Mariage class
import 'dart:convert';
class Marriage {
final String idUser, mariageStatus;
Marriage({required this.idUser, required this.mariageStatus});
factory Marriage.fromJson(Map<String, dynamic> json) {
return Marriage(
idUser: json['userID'], mariageStatus: json['mariageStatus']);
}
}
List<Marriage> marriageFromJson(dynamic jsonData) {
return List<Marriage>.from(jsonData.map((item) => Marriage.fromJson(item)));
}
// index
Future<List<Marriage>> fetchMarriage() async {
String route = AppConfig.API_ENDPOINT + "marriage";
final response = await http.get(route);
if (response.statusCode == 200) {
var jsonResp = json.decode(response.body);
//'[{"_id":"6194a2e65c504crb1d9af81d","userID":"6782452bd2ab63488c9f2663","mariageStatus":"Single"},{"_id":"6194a2959c534c01ft9rf24c","userID":"6785p58b41894b50b22db401","mariageStatus":"Married"}]'
return marriageFromJson(jsonResp);
} else {
throw Exception('Failed load $route, status : ${response.statusCode}');
}
}
A UserWithMariageStatus class, which will take User and Mariage Reference:
import 'package:flutter_fetch_data/mariage.dart';
import 'package:flutter_fetch_data/user.dart';
class UserWithMariageStatus {
final User user;
final Marriage mariage;
UserWithMariageStatus(this.user, this.mariage);
String get userId => user.id;
String get name => user.name;
String get phone => user.phone;
String get mariageStatus => mariage.mariageStatus;
}
List<UserWithMariageStatus> combineUserWithMarriageStatus(
List<User> user, List<Marriage> userMariage) {
List<UserWithMariageStatus> result = [];
// if userId is unique, iterate the lists and combine
for (var item in userMariage) {
result.add(UserWithMariageStatus(
user.singleWhere((element) => element.id == item.idUser), item));
}
return result;
}
Use it in your fetch calling function:
import 'package:flutter_fetch_data/mariage.dart';
import 'package:flutter_fetch_data/user.dart';
import 'package:flutter_fetch_data/user_with_mariage.dart';
void main(List<String> args) async {
List<User> userList = await fetchUser();
for (var user in userList) {
print("id: ${user.id}, name: ${user.name}, phone: ${user.phone}");
}
List<Marriage> mariageList = await fetchMarriage();
for (var mariage in mariageList) {
print("id: ${mariage.idUser}, mariageStatus: ${mariage.mariageStatus}");
}
List<UserWithMariageStatus> userWithMariageList =
combineUserWithMarriageStatus(userList, mariageList);
for (var userWithMariage in userWithMariageList) {
print(
"id: ${userWithMariage.userId}, name: ${userWithMariage.name}, phone: ${userWithMariage.phone}, mariageStatus: ${userWithMariage.mariageStatus}");
}
}
In a FutureBuilder, you could use it like that:
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Future<List<UserWithMariageStatus>>? getUserWithMarriageList() async {
final user = await fetchUser();
final marriage = await fetchMarriage();
return combineUserWithMarriageStatus(user, marriage);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "Test Fetch Future",
home: Scaffold(
body: FutureBuilder<List<UserWithMariageStatus>>(
future: getUserWithMarriageList(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView(
children: snapshot.data!
.map((e) => ListTile(
title: Text(
"id: ${e.userId}, name: ${e.name}, phone: ${e.phone}, marriage: ${e.mariageStatus}")))
.toList());
}
return const CircularProgressIndicator();
},
),
),
);
}
}