使用搜索过滤器时无法在启动页面时显示数据 Table 上的数据,但在搜索某些内容后显示数据?
Unable to show data on Data Table at startsup the page while using Search filter but showing data after search something?
我正在尝试使用 TextEditingController 在我的 flutter web 应用程序上实现数据行搜索 Table。数据来自 The API as Json formte using Employee 模型。
我使用 FutureBuilder 从 API 获取数据。我将快照数据作为列表插入到 'empList' 中。还创建了 empsFiltered 列表以显示搜索过滤数据。
问题是:启动时无法在数据表中显示实际数据。但是在搜索时和清除搜索文本字段后会显示数据。
我想在启动时显示实际数据。并且数据应显示为已搜索。
如何操作。
class EditorHome extends StatefulWidget {
const EditorHome({Key? key}) : super(key: key);
@override
_EditorHomeState createState() => _EditorHomeState();
}
class _EditorHomeState extends State<EditorHome> {
TextEditingController searchController = TextEditingController();
String _searchResult = '';
List empList = [];
List empsFiltered = [];
@override
void initState() {
super.initState();
empsFiltered = empList;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Fetch Data Table Example with search'),
),
body: SingleChildScrollView(
child: Column(
children: [
Card(
child: ListTile(
leading: const Icon(Icons.search),
title: TextField(
controller: searchController,
decoration: const InputDecoration(
hintText: 'Search', border: InputBorder.none),
onChanged: (value) {
setState(() {
_searchResult = value;
empsFiltered = empList
.where((e) =>
e.name.contains(_searchResult.toLowerCase()) ||
e.email.contains(_searchResult.toLowerCase()))
.toList();
});
}),
trailing: IconButton(
icon: const Icon(Icons.cancel),
onPressed: () {
setState(() {
searchController.clear();
_searchResult = '';
empsFiltered = empList;
});
},
),
),
),
FutureBuilder<List<Employees>>(
//initialData: const <Employees>[],
future: fetchResults(),
builder: (context, snapshot) {
if (snapshot.hasError ||
snapshot.data == null ||
snapshot.connectionState == ConnectionState.waiting) {
return const CircularProgressIndicator();
}
empList = snapshot.data!;
return DataTable(
headingTextStyle: const TextStyle(
fontWeight: FontWeight.bold, color: Colors.black),
headingRowHeight: 50,
showBottomBorder: true,
decoration: BoxDecoration(
border: Border.all(color: Colors.grey, width: 1)),
columns: const [
DataColumn(label: SizedBox(width: 30, child: Text('ID'))),
DataColumn(
label: SizedBox(width: 100, child: Text('Name'))),
DataColumn(
label: SizedBox(width: 100, child: Text('Email'))),
],
rows: List.generate(
empsFiltered.length,
(index) {
var emp = empsFiltered[index];
return DataRow(cells: [
DataCell(
Text(emp.id.toString()),
),
DataCell(
Text(emp.name),
),
DataCell(
Text(emp.email),
),
]);
},
).toList(),
);
},
),
],
),
),
);
}
}
下面是我的API:
Future<List<Employees>> fetchResults() async {
//List<Employees> _results = [];
Uri url = Uri.parse(" http:link ");
var response = await http.get(url);
var resultsJson = json.decode(response.body).cast<Map<String, dynamic>>();
List<Employees> emplist = await resultsJson
.map<Employees>((json) => Employees.fromJson(json))
.toList();
return emplist;
}
在此处发布以添加代码段:
您应该创建一个状态变量来包含 fetchResults 的结果,在您的 initState 中调用 fetchResults/set 该变量。使用该新变量作为 futureBuilder 的未来而不是直接调用函数
class _EditorHomeState extends State<EditorHome> {
Future<List> futureList;
@override
void initState() {
super.initState();
futureList = fetchResults();
}
@override
Widget build(BuildContext context) {
return Scaffold(
...
FutureBuilder<List<Employees>>(
future: futureList,
builder: (context, snapshot) {
...
);
}
}
我找到了解决办法。在本例中,我使用了两个 StatefulWidget。一个是用 fetchResults() 调用 Future 并转换成一个列表,第二个是 Table 和搜索过滤器,并将第一个 stateFulWidget List 调用到第二个 StatefulWidgets 的变量中,并将 initState 中的 List 变量设置为 empFiltered列表。工作正常。
示例代码:
class EditorHome extends StatefulWidget {
const EditorHome({Key? key}) : super(key: key);
@override
_EditorHomeState createState() => _EditorHomeState();
}
class _EditorHomeState extends State<EditorHome> {
List empList = [];
@override
Widget build(BuildContext context) {
return FutureBuilder<List<Employees>>(
future: fetchResults(),
builder: (context, snapshot) {
if (snapshot.hasError ||
snapshot.data == null ||
snapshot.connectionState == ConnectionState.waiting) {
return const CircularProgressIndicator();
}
empList = snapshot.data!;
return TableSec(fempList: empList);
});
}
}
class TableSec extends StatefulWidget {
final List fempList;
const TableSec({Key? key, required this.fempList}) : super(key: key);
@override
_TableSecState createState() => _TableSecState();
}
class _TableSecState extends State<TableSec> {
late List empList = widget.fempList;
List empsFiltered = [];
TextEditingController searchController = TextEditingController();
String _searchResult = '';
@override
void initState() {
super.initState();
empsFiltered = empList;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Table"),
),
body: SingleChildScrollView(
child: Column(
children: [
Card(
child: ListTile(
leading: const Icon(Icons.search),
title: TextField(
controller: searchController,
decoration: const InputDecoration(
hintText: 'Search', border: InputBorder.none),
onChanged: (value) {
setState(() {
_searchResult = value;
empsFiltered = empList
.where((e) =>
e.name.contains(_searchResult.toLowerCase()) ||
e.email.contains(_searchResult.toLowerCase()))
.toList();
//print(_searchResult);
});
}),
trailing: IconButton(
icon: const Icon(Icons.cancel),
onPressed: () {
setState(() {
searchController.clear();
_searchResult = '';
empsFiltered = empList;
});
},
),
),
),
DataTable(
headingTextStyle: const TextStyle(
fontWeight: FontWeight.bold, color: Colors.black),
headingRowHeight: 50,
showBottomBorder: true,
decoration: BoxDecoration(
border: Border.all(color: Colors.grey, width: 1)),
columns: const [
DataColumn(label: SizedBox(width: 30, child: Text('ID'))),
DataColumn(label: SizedBox(width: 100, child: Text('Name'))),
DataColumn(label: SizedBox(width: 100, child: Text('Email'))),
],
rows: List.generate(
empsFiltered.length,
(index) {
var emp = empsFiltered[index];
return DataRow(cells: [
DataCell(
Text(emp.id.toString()),
),
DataCell(
Text(emp.name),
),
DataCell(
Text(emp.email),
),
]);
},
).toList(),
)
],
),
),
);
}
}
我正在尝试使用 TextEditingController 在我的 flutter web 应用程序上实现数据行搜索 Table。数据来自 The API as Json formte using Employee 模型。 我使用 FutureBuilder 从 API 获取数据。我将快照数据作为列表插入到 'empList' 中。还创建了 empsFiltered 列表以显示搜索过滤数据。
问题是:启动时无法在数据表中显示实际数据。但是在搜索时和清除搜索文本字段后会显示数据。
我想在启动时显示实际数据。并且数据应显示为已搜索。
如何操作。
class EditorHome extends StatefulWidget {
const EditorHome({Key? key}) : super(key: key);
@override
_EditorHomeState createState() => _EditorHomeState();
}
class _EditorHomeState extends State<EditorHome> {
TextEditingController searchController = TextEditingController();
String _searchResult = '';
List empList = [];
List empsFiltered = [];
@override
void initState() {
super.initState();
empsFiltered = empList;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Fetch Data Table Example with search'),
),
body: SingleChildScrollView(
child: Column(
children: [
Card(
child: ListTile(
leading: const Icon(Icons.search),
title: TextField(
controller: searchController,
decoration: const InputDecoration(
hintText: 'Search', border: InputBorder.none),
onChanged: (value) {
setState(() {
_searchResult = value;
empsFiltered = empList
.where((e) =>
e.name.contains(_searchResult.toLowerCase()) ||
e.email.contains(_searchResult.toLowerCase()))
.toList();
});
}),
trailing: IconButton(
icon: const Icon(Icons.cancel),
onPressed: () {
setState(() {
searchController.clear();
_searchResult = '';
empsFiltered = empList;
});
},
),
),
),
FutureBuilder<List<Employees>>(
//initialData: const <Employees>[],
future: fetchResults(),
builder: (context, snapshot) {
if (snapshot.hasError ||
snapshot.data == null ||
snapshot.connectionState == ConnectionState.waiting) {
return const CircularProgressIndicator();
}
empList = snapshot.data!;
return DataTable(
headingTextStyle: const TextStyle(
fontWeight: FontWeight.bold, color: Colors.black),
headingRowHeight: 50,
showBottomBorder: true,
decoration: BoxDecoration(
border: Border.all(color: Colors.grey, width: 1)),
columns: const [
DataColumn(label: SizedBox(width: 30, child: Text('ID'))),
DataColumn(
label: SizedBox(width: 100, child: Text('Name'))),
DataColumn(
label: SizedBox(width: 100, child: Text('Email'))),
],
rows: List.generate(
empsFiltered.length,
(index) {
var emp = empsFiltered[index];
return DataRow(cells: [
DataCell(
Text(emp.id.toString()),
),
DataCell(
Text(emp.name),
),
DataCell(
Text(emp.email),
),
]);
},
).toList(),
);
},
),
],
),
),
);
}
}
下面是我的API:
Future<List<Employees>> fetchResults() async {
//List<Employees> _results = [];
Uri url = Uri.parse(" http:link ");
var response = await http.get(url);
var resultsJson = json.decode(response.body).cast<Map<String, dynamic>>();
List<Employees> emplist = await resultsJson
.map<Employees>((json) => Employees.fromJson(json))
.toList();
return emplist;
}
在此处发布以添加代码段:
您应该创建一个状态变量来包含 fetchResults 的结果,在您的 initState 中调用 fetchResults/set 该变量。使用该新变量作为 futureBuilder 的未来而不是直接调用函数
class _EditorHomeState extends State<EditorHome> {
Future<List> futureList;
@override
void initState() {
super.initState();
futureList = fetchResults();
}
@override
Widget build(BuildContext context) {
return Scaffold(
...
FutureBuilder<List<Employees>>(
future: futureList,
builder: (context, snapshot) {
...
);
}
}
我找到了解决办法。在本例中,我使用了两个 StatefulWidget。一个是用 fetchResults() 调用 Future 并转换成一个列表,第二个是 Table 和搜索过滤器,并将第一个 stateFulWidget List 调用到第二个 StatefulWidgets 的变量中,并将 initState 中的 List 变量设置为 empFiltered列表。工作正常。
示例代码:
class EditorHome extends StatefulWidget {
const EditorHome({Key? key}) : super(key: key);
@override
_EditorHomeState createState() => _EditorHomeState();
}
class _EditorHomeState extends State<EditorHome> {
List empList = [];
@override
Widget build(BuildContext context) {
return FutureBuilder<List<Employees>>(
future: fetchResults(),
builder: (context, snapshot) {
if (snapshot.hasError ||
snapshot.data == null ||
snapshot.connectionState == ConnectionState.waiting) {
return const CircularProgressIndicator();
}
empList = snapshot.data!;
return TableSec(fempList: empList);
});
}
}
class TableSec extends StatefulWidget {
final List fempList;
const TableSec({Key? key, required this.fempList}) : super(key: key);
@override
_TableSecState createState() => _TableSecState();
}
class _TableSecState extends State<TableSec> {
late List empList = widget.fempList;
List empsFiltered = [];
TextEditingController searchController = TextEditingController();
String _searchResult = '';
@override
void initState() {
super.initState();
empsFiltered = empList;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Table"),
),
body: SingleChildScrollView(
child: Column(
children: [
Card(
child: ListTile(
leading: const Icon(Icons.search),
title: TextField(
controller: searchController,
decoration: const InputDecoration(
hintText: 'Search', border: InputBorder.none),
onChanged: (value) {
setState(() {
_searchResult = value;
empsFiltered = empList
.where((e) =>
e.name.contains(_searchResult.toLowerCase()) ||
e.email.contains(_searchResult.toLowerCase()))
.toList();
//print(_searchResult);
});
}),
trailing: IconButton(
icon: const Icon(Icons.cancel),
onPressed: () {
setState(() {
searchController.clear();
_searchResult = '';
empsFiltered = empList;
});
},
),
),
),
DataTable(
headingTextStyle: const TextStyle(
fontWeight: FontWeight.bold, color: Colors.black),
headingRowHeight: 50,
showBottomBorder: true,
decoration: BoxDecoration(
border: Border.all(color: Colors.grey, width: 1)),
columns: const [
DataColumn(label: SizedBox(width: 30, child: Text('ID'))),
DataColumn(label: SizedBox(width: 100, child: Text('Name'))),
DataColumn(label: SizedBox(width: 100, child: Text('Email'))),
],
rows: List.generate(
empsFiltered.length,
(index) {
var emp = empsFiltered[index];
return DataRow(cells: [
DataCell(
Text(emp.id.toString()),
),
DataCell(
Text(emp.name),
),
DataCell(
Text(emp.email),
),
]);
},
).toList(),
)
],
),
),
);
}
}