У меня проблема с моей таблицей PaginatedDataTable во Flutter Web (1.20.0-8.0.pre2): мне нужно связать два будущих запроса, один в зависимости от первого. Например: Первый запрос возвращает массив задач json:
[ ["field1", "field2", 154631565, "field4"],["field5", "field6", 7862626, "field8"] ]"
Число в 3-й позиции - это идентификатор пользователя. Второй запрос получает пользователя с этим:
[ 154631565, "John", "Doe"]
Мой код основан на этом: https://github.com/AseemWangoo/experiments_with_web/tree/master/lib/data_table и https://flatteredwithflutter.com/using-paginateddatatable-in-flutter-web/
Если я запрашиваю только первую конечную точку, все работает, но у меня есть идентификаторы в таблице, а не имя и имя.
TaskDataTableAPi:
class TaskDataTableApi {
TaskDataTableApi._();
static Future<List<TaskModel>> fetchData() async {
final _completer = Completer<List<TaskModel>>();
try {
final response = await http.get(_query);
if (response.statusCode == 200) {
// print(response.body);
final _data = taskModelFromJson(response.body.replaceAll(r'\t', ' '));
_completer.complete(_data);
} else {
print('Error, Could not load Data');
throw Exception('Failed to load Data');
}
} catch (exc) {
_completer.completeError(<TaskModel>[]);
}
return _completer.future;
}
}
UserDataTableApi:
class UserDataTableApi {
UserDataTableApi._();
static Future<List<UserModel>> fetchData(maxRows) async {
final _completer = Completer<List<UserModel>>();
String _query = url;
_query += 'selectQuery?loginName=' + loginName;
_query += '&password=' + password;
_query += '&custId=' + custId;
_query += '&maxRows= ' + maxRows;
_query += '&output=json&';
_query += 'query=SELECT id, firstName,lastName, photo FROM USER';
try {
final response = await http.get(_query);
if (response.statusCode == 200) {
print(response.body);
final _data = userModelFromJson(response.body.replaceAll(r'\t', ' '));
_completer.complete(_data);
} else {
print('Error, Could not load Data');
throw Exception('Failed to load Data');
}
} catch (exc) {
_completer.completeError(<UserModel>[]);
}
return _completer.future;
}
static Future<List<UserModel>> getOneById(int id) async {
final _completer = Completer<List<UserModel>>();
try {
final response = await http.get(_query);
if (response.statusCode == 200) {
//print(response.body);
final _data = userModelFromJson(response.body.replaceAll(r'\t', ' '));
_completer.complete(_data);
} else {
print('Error, Could not load Data');
throw Exception('Failed to load Data');
}
} catch (exc) {
_completer.completeError(<UserModel>[]);
}
return _completer.future;
}
}
TaskDataTableNotifier
class TaskDataNotifier with ChangeNotifier {
TaskDataNotifier() {
fetchData();
}
List<TaskModel> get taskModel => _taskModel;
int get sortColumnIndex => _sortColumnIndex;
set sortColumnIndex(int sortColumnIndex) {
_sortColumnIndex = sortColumnIndex;
notifyListeners();
}
bool get sortAscending => _sortAscending;
set sortAscending(bool sortAscendindg) {
_sortAscending = sortAscending;
notifyListeners();
}
int get rowsPerPage => _rowsPerPage;
set rowsPerPage(int rowsPerPage) {
_rowsPerPage = rowsPerPage;
notifyListeners();
}
var _taskModel = <TaskModel>[];
int _sortColumnIndex;
bool _sortAscending = true;
int _rowsPerPage = PaginatedDataTable.defaultRowsPerPage;
Future<void> fetchData() async {
_taskModel = await TaskDataTableApi.fetchData();
for (TaskModel _row in _taskModel) {
if (_row.dev != null) {
print(_row.dev);
// List<UserModel> _user = await UserDataTableApi.getOneById(_row.dev);
// print(_user[0].firstName);
}
}
notifyListeners();
}
}
и страница с DataTable:
class MyTasksList extends StatelessWidget {
const MyTasksList({Key key}) : super(key: key);
static const String routeName = '/tasks';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: MyAppBar(),
drawer: MyDrawer(),
body: ChangeNotifierProvider<TaskDataNotifier>(
create: (_) => TaskDataNotifier(),
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Center(
child: Container(
width: 1500.0,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(
top: 10.0,
),
child: _MyTasksList(),
),
],
),
),
),
),
),
);
}
}
class _MyTasksList extends StatelessWidget {
@override
Widget build(BuildContext context) {
final _provider = context.watch<TaskDataNotifier>();
final _model = _provider.taskModel;
if (_model.isEmpty) {
return const SizedBox.shrink();
}
final _dtSource = TaskDataTableSource(
//onRowSelect: (index) => _showDetails(context, _model[index]),
onRowSelect: (index) => print("Pressed"),
taskData: _model,
);
return PaginatedDataTable(
actions: <IconButton>[
IconButton(
splashColor: Colors.transparent,
icon: const Icon(Icons.refresh),
onPressed: () {
_provider.fetchData();
_showSBar(context, "Refresh successful");
},
),
],
header: Text('Task List'),
columns: myColumns(_dtSource, _provider),
source: _dtSource,
onRowsPerPageChanged: (rowsPerPage) {
_provider.rowsPerPage = rowsPerPage;
},
sortAscending: _provider.sortAscending,
sortColumnIndex: _provider.sortColumnIndex,
rowsPerPage: _provider.rowsPerPage,
);
}
List<DataColumn> myColumns(
TaskDataTableSource _src,
TaskDataNotifier _provider,
) =>
<DataColumn>[
DataColumn(
label: Text('Type'),
onSort: (colIndex, asc) {
_sort<num>((task) => task.taskType, colIndex, asc, _src, _provider);
},
),
DataColumn(
label: Text('Name'),
onSort: (colIndex, asc) {
_sort<String>((task) => task.name, colIndex, asc, _src, _provider);
},
),
DataColumn(
label: Text('?'),
),
DataColumn(
label: Text('Origin'),
onSort: (colIndex, asc) {
_sort<num>(
(task) => task.customerId, colIndex, asc, _src, _provider);
},
),
DataColumn(
label: Text('Customer'),
onSort: (colIndex, asc) {
_sort<num>(
(task) => task.customerId, colIndex, asc, _src, _provider);
},
),
DataColumn(
label: Text('Complexity'),
onSort: (colIndex, asc) {
_sort<num>(
(task) => task.complexity, colIndex, asc, _src, _provider);
},
),
DataColumn(
label: Text('Value'),
onSort: (colIndex, asc) {
_sort<num>((task) => task.value, colIndex, asc, _src, _provider);
},
),
DataColumn(
label: Text('Dev'),
onSort: (colIndex, asc) {
_sort<num>((task) => task.dev, colIndex, asc, _src, _provider);
},
),
DataColumn(
label: Text('Corr'),
// onSort: (colIndex, asc) {
// _sort<num>((task) => task.cor, colIndex, asc, _src, _provider);
// },
),
DataColumn(
label: Text('Status'),
),
DataColumn(
label: Text('Created on'),
onSort: (colIndex, asc) {
_sort<DateTime>(
(task) => task.createdOn, colIndex, asc, _src, _provider);
},
),
DataColumn(
label: Text('Canceled on'),
),
DataColumn(
label: Text('Super Score'),
),
];
void _sort<T>(
Comparable<T> Function(TaskModel task) getField,
int colIndex,
bool asc,
TaskDataTableSource _src,
TaskDataNotifier _provider,
) {
_src.sort<T>(getField, asc);
_provider.sortAscending = asc;
_provider.sortColumnIndex = colIndex;
}
void _showSBar(BuildContext c, String textToShow) {
Scaffold.of(c).showSnackBar(
SnackBar(
content: Text(textToShow),
duration: const Duration(milliseconds: 2000),
),
);
}
}
Я пытался вызвать await then () в уведомлении, я вижу, что второй запрос запущен, но затем приложение не удается.
Спасибо за помощь.